I am working with PEB. I have managed to get inside _RTL_USER_PROCESS_PARAMETERS.
My Aim-> To know the memory address of argc and argv .( and if possible their values too ) only by using a binary file (.exe file)
My current approach-> To access commandline string(which resides inside the struct _RTL_USER_PROCESS_PARAMETERS.
i managed to get inside it by embedding asm inside a c program
mov eax:fs[0x30]
mov [PEBaddress] , eax
mov ebx, [eax+0x10]
mov [ProcessParameters] , ebx
i got the offsets 0x30 and 0x10 by studying the binary under windows debugger
now at the offset of 0x40 from Processparameters address lies the string commandline, which i believe is a buffer,which i further believe is holding the value of argc and argv.
Problem: I want to read that buffer , and get the address values of argc and argv (command line arguments passed to a process)
can anyone make this possible by providing me with a code for reading the buffer (as it is Unicode string) and get the required address.
Is there anyother way of doing this job ?(you can suggest me that also ,dont give me the option of printing the address of argc and argv inside main) i want static answers.
Windows does not pass argc and argv into a program. It passes the full literal command line, as a string. If the program in question even is a C program, then this parsing is done by the C runtime libraries embedded in that program.
Related
I'm doing x86 on Mac OS X with NASM. Copying an example and experimenting I noticed that my print command needed a four bytes pushed onto the stack after the other parameters but can't figure out why line five is necessary:
1 push dword len ;Length of message
2 push dword msg ;Message to write
3 push dword 1 ;STDOUT
4 mov eax,4 ;Command code for 'writing'
5 sub esp,4 ;<<< Effectively 'push' Without this the print breaks
6 int 0x80 ;SYSCALL
7 add esp,16 ;Functionally 'pop' everything off the stack
I am having trouble finding any documentation on this 'push the parameters to the stack' syntax that NASM/OS X seems to require. If anyone can point me to a resource for that in general that would most likely answer this question as well.
(Most of the credit goes to #Michael Petch's comment; I'm repeating it here so that it is an answer, and also in order to further clarify the reason for the additional four bytes on the stack.)
macOS is based on BSD, and, as per FreeBSD's documentation re system calls, by default the kernel uses the C calling conventions (which means arguments are pushed to the stack, from last to first), but assuming four extra bytes pushed to the stack, as "it is assumed the program will call a function that issues int 80h, rather than issuing int 80h directly".
That is, the kernel is not built for direct int 80h calls, but rather for code that looks like this:
kernel: ; subroutine to make system calls
int 80h
ret
.
.
.
; code that makes a system call
call kernel ; instead of invoking int 80h directly
Notice that call kernel would push the return address (used by the kernel subroutine's ret to return to calling code after the system call) onto the stack, accounting for four additional bytes – that's why it's necessary to manually push four bytes to the stack (any four bytes – their actual value doesn't matter, as it is ignored by the kernel – so one way to achieve this is sub esp, 4) when invoking int 80h directly.
The reason the kernel expects this behaviour – of calling a method which invokes the interrupt instead of invoking it directly – is that when writing code that can be run on multiple platforms it's then only needed to provide a different version of the kernel subroutine, rather than of every place where a system call is invoked (more details and examples in the link above).
Note: all the above is for 32-bit; for 64-bit the calling conventions are different – registers are used to pass the arguments rather than the stack (there's also a call convention for 32-bit which uses registers, but even then it's not the same registers), the syscall instruction is used instead of int 80h, and no extra four bytes (which, on 64-bit systems, would actually be eight bytes) need to be pushed.
Here is my code, but when I use my debugger I get an error once I reach the int21 h command which says:
Unhandled exception at 0x00007FF6E9B01034 in MP2_KyleRuiter.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
Program:
ExitProcess PROTO
.data
string DB 4bh, 79h, 6ch, 65h, 20h, 52h, 75h, 69h, 74h, 65h, 72h, 00h ; My Name
COUNT = ($-string) ; string length calculation
.code
main proc
mov rcx,COUNT ; loop counter
mov rsi,offset string
L1:
mov dl,[rsi] ;gets character from the array
mov ah,2 ;displays character
inc rsi; points to next character
Loop L1 ;decrements rcx until 0
mov rax, 4c00h
int 21h ; displays
RET
main ENDP
END
int 21h & co. is 16-bit MS-DOS stuff, while the rest of the code you wrote is x86 64bit assembly. On 64-bit Windows you are invoking god-knows-what interrupt handler, which results in a crash.
If you want to print stuff when running under 64 bit Windows you have to invoke the relevant syscalls (GetStdHandle to get a handle to the console, WriteFile to write the data); MASM makes this relatively simple through the INVOKE directive.
You can't use DOS interrupts, like int 21h, in a 64-bit Windows executable. Modern Windows isn't a DOS-based system, so it doesn't use that interface anymore.
If you want to write a DOS executable, you'll need to use 16-bit instructions, and run it in an emulator (like DOSBox).
If you want to write a 64-bit Windows executable, you'll need to use Windows library calls.
Pick one.
int 21h with AH set to 4Ch says to terminate with a return code. It looks like your debugger does not know how to step over/into a terminate. That makes some sense, I suppose.
Belay my last. I stand corrected.
You might find this helpful, though:
Why does using "int 21h" on Assembly x86 MASM cause my program to crash?
I'm currently debugging a simple c program, and was wondering about this assembly comparison:
cmpl $0x1d,-0xc(%ebp)
From what I gather, this is checking 29 against a location in memory.
How do I access this in gdb with the print or x commands? Is it as simple as looking at the location provided by ebp then moving 12 bits/bytes along or am I completely on the wrong track?
It is indeed comparing 29 with the location in memory that is offset 12 before ebp. Assuming the program you are disassembling uses frame pointers, it's reading a local variable off the stack, probably the first one. (Although the compiler is free to place them in any order.)
If it's not using frame pointers, disassemble the surrounding code and figure out what assigns ebp.
Yes, that's cmp with an immediate and a memory operand. And yes, the effective address used to load the memory operand is ebp - 12 bytes.
In gdb, $ebp gives you the contents of the ebp register as a value you can use in an expression. So you can do stuff like:
p $ebp-0xc # print the address
p *(int*)($ebp-0xc) # dereference it as an int*
x /4db $ebp-0xc # dump 4 8bit bytes (b) with %d formatting
Printing a char* prints the null-terminated string as well as the address, so you can do something like:
(gdb) p (char*)0x0804980B
$20 = 0x804980b "giants"
Of course, the address can be an expression involving a register value.
I am trying to link a user space library into a windows kernel driver. It has a reference to __iob_func which is part of "libcmt.lib" (user space library).
I don't have access to this function in winddk. So, I am planning to define a stub for __iob_func which will try to emulate the same functionality as done in user space library.
Does anyone know what __iob_func do? I found the declaration of the function in the header files. But I am not sure what functionality it exactly does.
__iob_func() returns a pointer to the array of FILE descriptors that holds stdin, stdout, stderr and any FILE objects opened through the C runtime library. See the MSVC runtime library source _file.c.
If your user-space library code actually tries to do much with the C runtime, you'll probably run into a lot of headaches linking it into your kernel driver. Good luck.
Disassemble the following c code. cl /Fa mycode.c
fflush (stdin) ;
fflush (stdout) ;
fflush (stderr) ;
This is basically what the assembly file output with the /Fa switch on the c file will look like:
call ___iob_func ; invoke the c function __iob_func
push eax ; invoke fflush with 1 parameter
call _fflush
add esp, 04h ; realign the stack adding 4 bytes to
; the stack pointer (esp).
So, apparently the __iob_func returns a pointer to array or structure of input output buffer information; hence the iob acronym followed by func (__iob_func). i stands for input, o for output, b for buffer, etc......
That's just the fflush(stdin) function. fflush(stdout) repeats the same 4 lines with the only difference for stdout in the second line:
push eax + 020h
So, apparently each array member is composed of 32 bytes or 8 double words.
For stderr the assembler posted push eax + 040h or eax + 64 bytes
Microsoft Developer Network (MSDN) doesn't document the __iob_func function. But it's declaration probably would be something like the following: lpReturn __iob_func ( void )
32 bit assembly usually returns the value of a function in the eax register. And when the input parameter value of a function is described as an addition to a register (e.g. eax + 020h), it usually means that its referring to a structure or array of some type. So eax would be the starting address of the structure or array. And eax + 020h would be a location in that structure where information for stdout begins. eax + 040h would be the location where stderr begins.
So basically, if you want to use the __iob_func in your c program, you would have to prototype the function, and then perhaps create your own personal lib
mylib.def
LIBRARY msvcrt.dll
EXPORTS
__iob_func
And then run lib on that file.
LIB /def:mylib.def /machine:x86
That should create a 32 bit library called mylib.lib which you can use to link into your program.
I would like to test a buffer-overflow by writing "Hello World" to console (using Windows XP 32-Bit). The shellcode needs to be null-free in order to be passed by "scanf" into the program I want to overflow. I've found plenty of assembly-tutorials for Linux, however none for Windows. Could someone please step me through this using NASM? Thxxx!
Assembly opcodes are the same, so the regular tricks to produce null-free shellcodes still apply, but the way to make system calls is different.
In Linux you make system calls with the "int 0x80" instruction, while on Windows you must use DLL libraries and do normal usermode calls to their exported functions.
For that reason, on Windows your shellcode must either:
Hardcode the Win32 API function addresses (most likely will only work on your machine)
Use a Win32 API resolver shellcode (works on every Windows version)
If you're just learning, for now it's probably easier to just hardcode the addresses you see in the debugger. To make the calls position independent you can load the addresses in registers. For example, a call to a function with 4 arguments:
PUSH 4 ; argument #4 to the function
PUSH 3 ; argument #3 to the function
PUSH 2 ; argument #2 to the function
PUSH 1 ; argument #1 to the function
MOV EAX, 0xDEADBEEF ; put the address of the function to call
CALL EAX
Note that the argument are pushed in reverse order. After the CALL instruction EAX contains the return value, and the stack will be just like it was before (i.e. the function pops its own arguments). The ECX and EDX registers may contain garbage, so don't rely on them keeping their values after the call.
A direct CALL instruction won't work, because those are position dependent.
To avoid zeros in the address itself try any of the null-free tricks for x86 shellcode, there are many out there but my favorite (albeit lengthy) is encoding the values using XOR instructions:
MOV EAX, 0xDEADBEEF ^ 0xFFFFFFFF ; your value xor'ed against an arbitrary mask
XOR EAX, 0xFFFFFFFF ; the arbitrary mask
You can also try NEG EAX or NOT EAX (sign inversion and bit flipping) to see if they work, it's much cheaper (two bytes each).
You can get help on the different API functions you can call here: http://msdn.microsoft.com
The most important ones you'll need are probably the following:
WinExec(): http://msdn.microsoft.com/en-us/library/ms687393(VS.85).aspx
LoadLibrary(): http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx
GetProcAddress(): http://msdn.microsoft.com/en-us/library/ms683212%28v=VS.85%29.aspx
The first launches a command, the next two are for loading DLL files and getting the addresses of its functions.
Here's a complete tutorial on writing Windows shellcodes: http://www.codeproject.com/Articles/325776/The-Art-of-Win32-Shellcoding
Assembly language is defined by your processor, and assembly syntax is defined by the assembler (hence, at&t, and intel syntax) The main difference (at least i think it used to be...) is that windows is real-mode (call the actual interrupts to do stuff, and you can use all the memory accessible to your computer, instead of just your program) and linux is protected mode (You only have access to memory in your program's little cubby of memory, and you have to call int 0x80 and make calls to the kernel, instead of making calls to the hardware and bios) Anyway, hello world type stuff would more-or-less be the same between linux and windows, as long as they are compatible processors.
To get the shellcode from your program you've made, just load it into your target system's
debugger (gdb for linux, and debug for windows) and in debug, type d (or was it u? Anyway, it should say if you type h (help)) and between instructions and memory will be the opcodes.
Just copy them all over to your text editor into one string, and maybe make a program that translates them all into their ascii values. Not sure how to do this in gdb tho...
Anyway, to make it into a bof exploit, enter aaaaa... and keep adding a's until it crashes
from a buffer overflow error. But find exactly how many a's it takes to crash it. Then, it should tell you what memory adress that was. Usually it should tell you in the error message. If it says '9797[rest of original return adress]' then you got it. Now u gotta use ur debugger to find out where this was. disassemble the program with your debugger and look for where scanf was called. Set a breakpoint there, run and examine the stack. Look for all those 97's (which i forgot to mention is the ascii number for 'a'.) and see where they end. Then remove breakpoint and type the amount of a's you found out it took (exactly the amount. If the error message was "buffer overflow at '97[rest of original return adress]" then remove that last a, put the adress you found examining the stack, and insert your shellcode. If all goes well, you should see your shellcode execute.
Happy hacking...