I am by all means no assembler expert, and my knowledge on this topic is rather shallow, but I was curious on what the Microsoft VC++ Compiler does in a simple function call that does nothing else but returning a value.
Let us have the following function:
unsigned long __stdcall someFunction ( void * args) {
return 0;
}
Now, I know that with __stdcall calling convention the CALLEE is responsible for stack unwinding, and with __cdecl the CALLER of the function takes care of this. But for this example I would like to stick to the former.
With an non-optimized debug build I saw that the following output is being produced:
unsigned long __stdcall someFunction (void * args) {
00A31730 push ebp
00A31731 mov ebp,esp
00A31733 sub esp,0C0h
00A31739 push ebx
00A3173A push esi
00A3173B push edi
00A3173C lea edi,[ebp-0C0h]
00A31742 mov ecx,30h
00A31747 mov eax,0CCCCCCCCh
00A3174C rep stos dword ptr es:[edi]
return 0;
00A3174E xor eax,eax
}
00A31750 pop edi
00A31751 pop esi
00A31752 pop ebx
00A31753 mov esp,ebp
00A31755 pop ebp
00A31756 ret 4
I would thank anyone to explain this snippet of code for me if possible. I know that the xor statement actually resets the eax register to produce the zero return value. Also the ret 4 is self-explanatory to me. I think the edi, esi and ebx registers are pushed before and popped after to save the original state, so that the function can use them freely maybe. But for the rest - I have no clue.
Any answer is very much appreciated! :)
Thanks!
So you're asking what these lines do:
00A3173C lea edi,[ebp-0C0h]
00A31742 mov ecx,30h
00A31747 mov eax,0CCCCCCCCh
00A3174C rep stos dword ptr es:[edi]
In Visual C++ debugging runtime library, uninitialized stack memory is initialized to contain 0xCC bytes. This is what these instructions do.
At the beginning of the ASM code, there is the instruction sub esp,0C0h that allocates 0xC0 bytes for the stack. However, there is no local variables used in this function, so where does this come from? It's for Edit+Continue support: you're able to add local variables and continue debugging.
The 0xCC opcode means the INT 3 x86 assembly instruction, so if you try to execute that code (accidentally due to a bug), the program will throw an INT 3 exception which will be handled by the debugger or OS. So it's not just some random value.
Related
I am currently learning the basics of assembly language for LINUX OS, x84-64 processors, GCC compilers and I came across an example which tries to translate into assembly the following C function:
unsigned long fact(unsigned n)
{
if (n<=1)
return 1;
else
return n*fact(n-1);
}
This is the solution proposed:
.intel_syntax noprefix
.text
.global fact
.type fact, #function
fact: PUSH RBP
MOV RBP, RSP
CMP EDI, 1
JBE retour_un
PUSH RDI
DEC RDI
SUB RSP, 8
CALL fact
ADD RSP, 8
POP RDI
MUL RDI
JMP retour
retour_un: MOV RAX, 1
retour: POP RBP
RET
However, I don't exactly how this works. From what I have read the CALL instruction places on the stack the value of RIP and then jumps to wherever its argument shows. In this case, I understand up to the point where CALL fact is used. If this instruction is implemented everytime then everytime the program will start form the beginning until RDI==1 in which case it will jump to retour_un and everything that there is in between will never be executed. Could someone explain to me where I am mistaken and how this segment of assembly code actually works?
"call 0x80482f0 <puts#plt>"? Just need help with one line of code in a 'hello world' program in x86 assembly.
NOTE: i'm running ubuntu linux while programming/debugging this, using gcc as the compiler and gdb for the debugger.
I am reading Hacking: The art of Exploitation V2 and I compiled this C program:
1 #include <stdio.h>
2
3 int main()
4 {
5 int i;
6 for(i=0; i<10; i++)
7 {
8 printf("Hello, world\n");
9 }
10 return 0;
into this program in assembly:
0x080483b4 <+0>: push ebp
0x080483b5 <+1>: mov ebp,esp
0x080483b7 <+3>: and esp,0xfffffff0
0x080483ba <+6>: sub esp,0x20
0x080483bd <+9>: mov DWORD PTR [esp+0x1c],0x0
0x080483c5 <+17>: jmp 0x80483d8 <main+36>
0x080483c7 <+19>: mov DWORD PTR [esp],0x80484b0
0x080483ce <+26>: call 0x80482f0 <puts#plt>
=> 0x080483d3 <+31>: add DWORD PTR [esp+0x1c],0x1
0x080483d8 <+36>: cmp DWORD PTR [esp+0x1c],0x9
0x080483dd <+41>: jle 0x80483c7 <main+19>
0x080483df <+43>: mov eax,0x0
0x080483e4 <+48>: leave
0x080483e5 <+49>: ret
now.. i understand every portion of this program, until it gets to:
0x080483ce <+26>: call 0x80482f0 <puts#plt>
what i do not understand is.. if "Hello, world\n" is stored at 0x80484b0, and that address is then stored into the address at ESP, why does the:
0x080483ce <+26>: call 0x80482f0 <puts#plt>
refer to 0x80482f0, instead of [esp] or just "0x80484b0" to print "Hello, world\n" to the screen? i used gdb and i cannot figure out what exactly is being referenced with 0x80482f0.. any help would be great
thanks (and remember, im just starting out with this stuff, so im a noob)
also.. i copy and pasted the disassembled main function from gdb for convenience, if you need any more info, just ask. and if you would like to explain that one command for me, that would be great as well because i've only used "int 80h"'s for printing stuff to the screen before
0x80482f0 is the address of the puts function. To be more precise, it points to the entry for puts() in the program linker table (PLT) - basically just a bunch of JMP <some routine in a so-library>s (it's a little more complex than that, but that's not important for this discussion). The puts function looks for its argument on the stack - ie, at [esp].
You may be wondering where that puts() call came from - the compiler here was smart enough to see that you didn't actually use any format string parameters in your call to printf(), and replaced that call with a call to the (somewhat faster) puts(). If you'll look closely, you'll see that it also removed the newline from your string, because puts() appends a newline after printing the string it is given.
I have problems with inline assembly in visual c++ 2010 Ultimate (Windows 7 Professional). All my inline assemblies don't work, when I use chars, DWORD strings etc etc... So I copied this code from MSDN in my console application:
// InlineAssembler_Calling_C_Functions_in_Inline_Assembly.cpp
// processor: x86
#include <stdio.h>
char format[] = "%s %s\n";
char hello[] = "Hello";
char world[] = "world";
int main( void )
{
__asm
{
mov eax, offset world
push eax
mov eax, offset hello
push eax
mov eax, offset format
push eax
call printf
//clean up the stack so that main can exit cleanly
//use the unused register ebx to do the cleanup
pop ebx
pop ebx
pop ebx
}
}
I have nothing except those lines in my application, result: The string doesn't get printed and the application crashs. Any ideas why this happens?
Project + Properties, C/C++, Code Generation, select /MTd. Repeat for the Release configuration, select /MT.
If you want to make it work with the non-static version of the CRT then you'll need to write the call like this:
call dword ptr printf
Exports from a DLL need to be called indirectly.
I am assuming that popping into ebx is the reason. It is Your responsibility to maintain the integrity of all registers, excluding eax. Try popping into eax instead.
When I try to make an immediate call or jump in VC++ 2010 inline assembler
_asm
{
call 00405B90h;
jmp 00405B90h;
jmp far 00405B90h;
}
it generates an error
C2415: improper operand type
Is it possbile and how to do this?
So far I have a work around:
_asm
{
push 00405B90h; // This is a jump work around
call 00405B90h;
}
depending on what you want to call, either set a var to the address and do:
DWORD var = 0xDEADBEEF;
__asm jmp [var]
or, what I do:
__asm
{
mov eax,ModuleBase
add eax,RVA
call eax ;obviously call can be jmp
}
you can easily macro this(probably a good idea to add a register param):
#define JMP_IMM(x) __asm mov eax,x \
__asm jmp eax
Unfortunately MASM doesn't support relative calls to absolute addresses, and other assemblers like NASM can't do it for COFF object files either. So toolchain limitations force you to use this less efficient machine code with an indirect call or jmp.
How to write an absolute target for a near direct relative call/jmp in MASM
Error when calling function in user32.dll directly
__asm jmp fword ptr cs:[00405B90h]
I have a simple recursive function RCompare() that calls a more complex function Compare() which returns before the recursive call. Each recursion level uses 248 bytes of stack space which seems like way more than it should. Here is the recursive function:
void CMList::RCompare(MP n1) // RECURSIVE and Looping compare function
{
auto MP ne=n1->mf;
while(StkAvl() && Compare(n1=ne->mb))
RCompare(n1); // Recursive call !
}
StkAvl() is a simple stack space check function that compares the address of an auto variable to the value of an address near the end of the stack stored in a static variable.
It seems to me that the only things added to the stack in each recursion are two pointer variables (MP is a pointer to a structure) and the stuff that one function call stores, a few saved registers, base pointer, return address, etc., all 32-bit (4 byte) values. There's no way that is 248 bytes is it?
I don't no how to actually look at the stack in a meaningful way in Visual Studio 2008.
Thanks
Added disassembly:
CMList::RCompare:
0043E000 push ebp
0043E001 mov ebp,esp
0043E003 sub esp,0E4h
0043E009 push ebx
0043E00A push esi
0043E00B push edi
0043E00C push ecx
0043E00D lea edi,[ebp-0E4h]
0043E013 mov ecx,39h
0043E018 mov eax,0CCCCCCCCh
0043E01D rep stos dword ptr es:[edi]
0043E01F pop ecx
0043E020 mov dword ptr [ebp-8],edx
0043E023 mov dword ptr [ebp-14h],ecx
0043E026 mov eax,dword ptr [n1]
0043E029 mov ecx,dword ptr [eax+20h]
0043E02C mov dword ptr [ne],ecx
0043E02F mov ecx,dword ptr [this]
0043E032 call CMList::StkAvl (41D46Fh)
0043E037 test eax,eax
0043E039 je CMList::RCompare+63h (43E063h)
0043E03B mov eax,dword ptr [ne]
0043E03E mov ecx,dword ptr [eax+1Ch]
0043E041 mov dword ptr [n1],ecx
0043E044 mov edx,dword ptr [n1]
0043E047 mov ecx,dword ptr [this]
0043E04A call CMList::Compare (41DA05h)
0043E04F movzx edx,al
0043E052 test edx,edx
0043E054 je CMList::RCompare+63h (43E063h)
0043E056 mov edx,dword ptr [n1]
0043E059 mov ecx,dword ptr [this]
0043E05C call CMList::RCompare (41EC9Dh)
0043E061 jmp CMList::RCompare+2Fh (43E02Fh)
0043E063 pop edi
0043E064 pop esi
0043E065 pop ebx
0043E066 add esp,0E4h
0043E06C cmp ebp,esp
0043E06E call #ILT+5295(__RTC_CheckEsp) (41E4B4h)
0043E073 mov esp,ebp
0043E075 pop ebp
0043E076 ret
Why 0E4h?
More Info:
class mch // match node structure
{
public:
T_FSZ c1,c2; // file indexes
T_MSZ sz; // match size
enum ntyp typ; // type of node
mch *mb,*mf; // pointers to next and previous match nodes
};
typedef mch * MP; // for use in casting (MP) x
Should be a plain old pointer right? The same pointers are in the structure itself and they are just normal 4 byte pointers.
Edit: Added:
#pragma check_stack(off)
void CMList::RCompare(MP n1) // RECURSIVE and Looping compare function
{
auto MP ne=n1->mf;
while(StkAvl() && Compare(n1=ne->mb))
RCompare(n1); // Recursive call !
} // end RCompare()
#pragma check_stack()
But it didn't change anything. :(
Now what?
Note that on debug mode the compiler binds many bytes from the stack, on every function,
to catch buffer overflow bugs.
0043E003 sub esp, 0E4h ; < -- bound 228 bytes
...
0043E00D lea edi,[ebp-0E4h]
0043E013 mov ecx, 39h
0043E018 mov eax, 0CCCCCCCCh ; <-- sentinel
0043E01D rep stos dword ptr es:[edi] ; <-- write sentinels
Edit: the OP Harvey found the pragma that turns on/off stack probes.
check_stack
Instructs the compiler to turn off
stack probes if off (or –) is
specified,
or to turn on stack probes
if on (or +) is specified.
#pragma check_stack([ {on | off}] )
#pragma check_stack{+ | –}
Update: well, probes is another story, as it appears.
Try this: /GZ (Enable Stack Frame Run-Time Error Checking)
That also depends on the compiler and the architecture you're running - e.g. it could be aligning to 256 bytes for faster execution, so that each level uses the 8 bytes of the variable + 248 padding.
I guess some space has to be allocated for exception handling. Did you look at the disassembly?
In Visual Studio you can look at the register "esp", the stack pointer, in a watch (or register) windows. Set a breakpoint in your function between one call and the next to see who much stack you consume.
On a pain function on debug mode in Visual Studio 2008 it is 16 byes per function call.