PDA

View Full Version : Opaque arguments


jackall
June 22nd, 2008, 03:52
This request is related to the Stack frame.
It is in continuation to my endeavor to acquire at least a basic level of that elusive reverenced skill aka reversing.

#include<stdio.h>
int test (int h)
{
if (h==3)
{
return 1;
}}

void main (int argc, char *argv [] )
{
int j, i=3;

j=test (i); //-------> Line 12

}

Code:
“When a function is called, its arguments are pushed on the stack.”

A function is called from line-12 and the argument (int h) is pushed on the stack frame (please correct me !). Then EBP value is saved on the stack (Seen in asm as PUSH EBP)...Return address is saved on the stack. So,EBP+4 is the return address.

Now, EBP is given a new value . Then, ESP makes room to accommodate local variable (i and j).
In the Assembly below, it can be seen that an 8-byte space is allotted for the two local variables present,

00401220 > $ 55 PUSH EBP
00401221 . 89E5 MOV EBP, ESP
00401223 . 83EC 08 SUB ESP, 8

00401226 . C70424 010000> MOV DWORD PTR SS: [ESP], 1
0040122D . FF15 D0504000 CALL DWORD PTR DS:[<&msvcrt.__set_app_type>] ; msvcrt.__set_app_type
00401233 . E8 C8FEFFFF CALL Return.00401100

What i fail to see in asm is the:
(1) Code that pushed the arguments to the stack Frame and the
(2) Instruction that saved the return address on the stack frame.

It may be right there gawping at my blindness, but right now iam opaque.
The executable is attached for your helpful glance if ever needed.

Regards…

Admiral
June 22nd, 2008, 05:19
You have been fooled by the compiler .
The function you are looking at isn't main(), but a compiler-generated entry-point that is supposed to act transparently to your program. If you step into that call at 0x401233 (and most probably through a fair amount of further auto-generated initialisation code) you'll eventually find your way to main().

This is one of the 'problems' of C++, from a reverser's perspective. Behind the scenes, quite a lot goes on that we aren't told about. The more of these optional compiler features we use, the more abstracted our code becomes, often to the point where you'd need to trace through thousands of program-prolog instructions before encountering anything familiar. Assuming you're using something like Visual C++, there is a very delicate balance of compiler and linker settings you can enforce that will produce a clean, naked program, but this is increasingly difficult to pull off, especially when using anything more than a minimal set of libraries and language extensions.

What I find to be the best approach when trying to analyse compiler-generated code is to prepend your function with something unique, such as a call to IsDebuggerPresent(), which you can set a breakpoint on in Olly and hit run, ensuring that you know where you'll land when it breaks.

naides
June 22nd, 2008, 05:42
Another suggestion to find your own code inside the code woods: Instead of using such a plain constant such as h=3; or (h==3 for testing), make h something much more interesting and distinctive, like h = 1122332211 or h = 0xDEAD. Then search for the numeric constant inside the decompilation. Your code should be around it. . .

ant
June 22nd, 2008, 14:46
Code:
What i fail to see in asm is the:
(1) Code that pushed the arguments to the stack Frame and the
(2) Instruction that saved the return address on the stack frame.


question is understandable but not the answers .
a little simplification can help and may be of some use to the newbies to whome it is meant for !

naides
June 22nd, 2008, 18:32
Quote:
[Originally Posted by ant;75335]
question is understandable but not the answers .
a little simplification can help and may be of some use to the newbies to whom it is meant for !


A simpler answer for our arthropod friend: Jackall is looking for the code he wrote, and he is not finding it because he is looking in the wrong place.

From IDA disassembly,

Code:
.text:00401290 ; =============== S U B R O U T I N E =======================================
.text:00401290
.text:00401290 ; Attributes: bp-based frame
.text:00401290
.text:00401290 sub_401290 proc near ; CODE XREF: _main+37p
.text:00401290
.text:00401290 var_4 = dword ptr -4 ; This is an internal bool variable, lets call it answer
.text:00401290 arg_0 = dword ptr 8 ; This is the parameter (argument) h
.text:00401290
.text:00401290 push ebp
.text:00401291 mov ebp, esp
.text:00401293 sub esp, 4
.text:00401296 cmp [ebp+arg_0], 3 ; if h==3
.text:0040129A jnz short loc_4012A5
.text:0040129C mov [ebp+var_4], 1 ; answer = true
.text:004012A3 jmp short loc_4012AC
.text:004012A5 ; ---------------------------------------------------------------------------
.text:004012A5
.text:004012A5 loc_4012A5: ; CODE XREF: sub_401290+Aj
.text:004012A5 mov [ebp+var_4], 0 ;else answer = false
.text:004012AC
.text:004012AC loc_4012AC: ; CODE XREF: sub_401290+13j
.text:004012AC mov eax, [ebp+var_4] ; store answer in eax
.text:004012AF leave
.text:004012B0 retn ; Return the bool answer stored in eax
.text:004012B0 sub_401290 endp
.text:004012B0
.text:004012B1
.text:004012B1 ; =============== S U B R O U T I N E =======================================
.text:004012B1


This is the place where the function:
Code:
int test (int h);

code resides.

Looking at the place where this function gets called:
Code:
.text:004012B1 ; =============== S U B R O U T I N E =======================================
.text:004012B1
.text:004012B1 ; Attributes: bp-based frame
.text:004012B1
.text:004012B1 ; int __cdecl main(int argc, const char **argv, const char *envp)
.text:004012B1 _main proc near ; CODE XREF: ___mingw_CRTStartup+E2p
.text:004012B1
.text:004012B1 var_18 = dword ptr -18h
.text:004012B1 var_14 = dword ptr -14h
.text:004012B1 var_C = dword ptr -0Ch
.text:004012B1 var_8 = dword ptr -8
.text:004012B1 var_4 = dword ptr -4
.text:004012B1 argc = dword ptr 8
.text:004012B1 argv = dword ptr 0Ch
.text:004012B1 envp = dword ptr 10h
.text:004012B1
.text:004012B1 push ebp
.text:004012B2 mov ebp, esp
.text:004012B4 sub esp, 18h
.text:004012B7 and esp, 0FFFFFFF0h
.text:004012BA mov eax, 0
.text:004012BF add eax, 0Fh
.text:004012C2 add eax, 0Fh
.text:004012C5 shr eax, 4
.text:004012C8 shl eax, 4
.text:004012CB mov [ebp+var_C], eax
.text:004012CE mov eax, [ebp+var_C]
.text:004012D1 call ___chkstk
.text:004012D6 call ___main
.text:004012DB mov [ebp+var_8], 3 i = 3
.text:004012E2 mov eax, [ebp+var_8] ; now i gets moved to eax
.text:004012E5 mov [esp+18h+var_18], eax ;now eax gets loaded into the stack, there is no push of a parameter
.text:004012E8 call sub_401290 ; call test(i)
.text:004012ED mov [ebp+var_4], eax ; the answer returned in eax is stored in j
.text:004012F0 cmp [ebp+var_4], 1 ; is j== true ?
.text:004012F4 jnz short loc_401309
.text:004012F6 mov eax, [ebp+var_4] ;weird stuff
.text:004012F9 mov [esp+18h+var_14], eax ;weird stuff
.text:004012FD mov [esp+18h+var_18], offset aValueOfJD ; "value of j=%d"
.text:00401304 call printf
.text:00401309
.text:00401309 loc_401309: ; CODE XREF: _main+43j
.text:00401309 call getchar
.text:0040130E leave
.text:0040130F retn
.text:0040130F _main endp



The calling convention is not typical, quite convoluted. Indeed there is no push into the stack.
What compiler are you using?

ant
June 22nd, 2008, 22:41
You guys are really talented ~~ envy u

There are 10 entries at 00401290 as given by u.
=============== S U B R O U T I N E ====================
.text:00401290
.text:00401290 ; Attributes: bp-based frame
.text:00401290
.text:00401290 sub_401290 proc near ; CODE XREF: _main+37p
.text:00401290
.text:00401290 var_4 = dword ptr -4 ; This is an internal bool variable, lets call it answer
.text:00401290 arg_0 = dword ptr 8 ; This is the parameter (argument) h
.text:00401290

I use Ollydebugger. there I don’t see the info u have given. And ther’s just one at

00401290 /$ 55 PUSH EBP

Kayaker
June 22nd, 2008, 22:48
ant, that's IDA output convention. Many lines, even comments and spacing, may appear to have an "address" associated with them in IDA disassembly, but they all refer to only 1 instruction.

naides
June 23rd, 2008, 05:30
Jackall: For the kind of learning you are currently doing, I suggest:
Get yourself an old, "classical" compiler like borland's C++ 5.0 and/or an old version of visualstudio.

Find a copy of Hacker Disassembling Uncovered 2nd edition by Kris Kaspersky. He explains this stuff in excruciating detail.

jackall
June 23rd, 2008, 07:12
Admiral, the info you have provided is an eye opener.
Code:
You have been fooled by the compiler.The function you are looking at isn't
main(), but a compiler-generated entry-point that is supposed to act
transparently to your program. If you step into that call at 0x401233 (and most
probably through a fair amount of further auto-generated initialisation code)
you'll eventually find your way to main ().


Yes ! I stepped into that call: 00401233 which brought me here:

00401100 $ 55 PUSH EBP
00401101 . 89E5 MOV EBP, ESP
00401103 . 53 PUSH EBX
00401104 . 83EC 24 SUB ESP, 24
00401107 . 8D5D F8 LEA EBX, DWORD PTR SS: [EBP-8]
0040110A . C70424 001040> MOV DWORD PTR SS: [ESP], Return.00401000

Here i face another paradox.
i need to ask you if this is place iam looking for i.e. the main () function.

If this is The main (), i need just 2-more points for clarification. i will not bother you again in this context.
It is a promise. In the same breadth, let me remind you….that...
“Promises are made to be broken and lies are meant to be kept “

Well...
(1). SUB ESP, 24
Here, a 24 byte of space is allotted for local variables. Why? i have declared just 2-variables (i and j) which need only 8-bytes.

(2). LEA EBX, DWORD PTR SS: [EBP-8]
[EBP-8] represent the argument on the stack related to the line :
int test (int h) {

(3). [EBP-4] could be return address similarly ……

i said just 2-points , so 'am not beyond that...

jackall
June 23rd, 2008, 07:22
Code:
that's IDA output convention. Many lines, even comments and spacing, may appear
to have an "address" associated with them in IDA disassembly, but they all refer
to only 1 instruction.


Thank you ..Kayaker

ant
June 23rd, 2008, 08:39
naides,

answer was difficult to understand but the explanation that followed was head spinning.

I give up struggling...dead and out.

Polaris
June 23rd, 2008, 09:36
@@Naides:

That code is rather typical output for MinGW:

Quote:
.text:004012B1
.text:004012B1 ; int __cdecl main(int argc, const char **argv, const char *envp)
.text:004012B1 _main proc near ; CODE XREF: ___mingw_CRTStartup+E2p
.text:004012B1


MinGW has calculated the overall stack needs for the procedure, and moves arguments in the right place instead than pushing them. If I am not mistaken, this behaviour should be a speed optimization.

@@Jackall: [edit ] as naides already pointed out [/edit ] I would say that the code generated by this compiler is definetely not the best for a beginner to start with. I suggest that for your next tests you use VC instead: you can get the VC++ Express for free, which is also pretty good for non-commercial coding.

Get it here:

Quote:
hxxp://www.microsoft.com/express/vc/


Keep up the study

ant
June 23rd, 2008, 21:11
Is it advisable to use IDA Pro disassembler by a beginner ?????

Woodmann
June 23rd, 2008, 22:32
You gotta start somewhere.

Why not IDA.

Woodmann

tHE mUTABLE
June 24th, 2008, 00:26
Why don't you try to debug your program at the source code level in which you can see the Assembly instructions in parallel with the C/C++ instructions...

ant
June 24th, 2008, 01:11
Code:
try to debug your program at the source code level in which you can see the
Assembly instructions in parallel with the C/C++ instructions...
Right now iam using Ollydebugger.
So, please... let me know how to do it with Ollydebugger where one can "see the Assembly instructions in parallel with the C/C++”.i mean configuration part of Olly??

OR
…i can begin with IDA free 4.9 freeware … or
…may be start with IDA Pro 5.2 evaluation version.

seeking your advice!

jackall
June 24th, 2008, 11:25
naides …comments..
Code:
Jackall is looking for the code he wrote, and he is
not finding it because he is looking in the wrong place.

i had to open the executable in IDA pro and as you have point out it’s all right there. And you have clearly commented all the proceedings here.

Code:
mov [ebp+var_8], 3 i = 3
.text:004012E2 mov eax, [ebp+var_8] ; now i gets moved to eax
.text:004012E5 mov [esp+18h+var_18], eax ; now eax gets loaded into
; the stack, there is no push of a parameter

.text:004012E8 call sub_401290 ; call test (i)
.text:004012ED mov [ebp+var_4], eax ; the answer returned in eax is stored in j
.text:004012F0 cmp [ebp+var_4], 1 ; is j== true?

.text:004012FD mov [esp+18h+var_18], offset aValueOfJD ; "value of j=%d"
.text:00401304 call printf

It took me a little time to distinguish it ….though I haven’t yet able to understand it fully well yet.
what does the comment mean “ there is no push of a parameter ”?

however...
Thank you for your taking the time to comment all relevant lines of code without which, those codes would have remained intimidating to me as usual.

Allow me also to thank …. Admiral .. Kayaker .. Polaris ..tHE mUTABLE .... and of course .. Woodmann for their contributions and encouragement .

Regards…

naides
June 24th, 2008, 11:35
Here is a little rant I had about The stack dynamics
http://71.6.196.237/forum/showthread.php?t=5849&highlight=good+mood

Also look at the calling conventions blog by Nynaeve
http://71.6.196.237/forum/search.php?searchid=451507

What I meant with my comment "there is no push of a parameter" is that usually before a function is called, test(i), the value of i is pushed into the stack.
In your code, this is not happening. That is why I suggest you using a more conventional C++ compiler, without optimizations and with more typical function calling conventions.

blabberer
June 25th, 2008, 07:00
referance to bcc and ollydbg thats my playground

get bcc 5.5 free commandline tools from borland (register with maybe penguin , penguin @a ntartica.com ) just a sleek 9 mb package it should be in your desktop in under a minute with todays inet speeds
execute the installer -> point it to some root directory say f:\
it will put all the contents into f:\borland\bcc55
add f:\borland\bcc55\bin to your environment variable start->mycomputers->properties->advanced->enviroment vars ->path -> edit -> append without quotes ";f:\borland\bcc55\bin"

goto f:\borland\bcc55\bin and create these two text files
bcc32.cfg containing
Code:

F:\>type f:\Borland\BCC55\Bin\bcc32.cfg
-I"F:\borland\bcc55\include"
-L"F:\borland\bcc55\lib"
F:\>


and ilink32.cfg containing
Code:

F:\>type f:\Borland\BCC55\Bin\ilink32.cfg
-L"F:\borland\bcc55\lib"
F:\>


you are all set now for compiling your first hello world from any directory

Code:

start -> run -> cmd -> cd /d f:\borland/bcc55
md MyCrapExps
edit MyFirstCrapExp.c

type out your code


Code:

F:\Borland\BCC55\MYCRAP~1>type myFisrtCrapExp.c
#include <stdio.h>

int test (int h)
{
if (h == 3)
{
return 0xDEAD1E55;
}
else
{
return 0xDEAD;
}
}


void main (void)

{
int j, i = 3;

printf("My First Crap Experiment with bcc 5.5 and ollydbg for Source lev
el Debugging\n";
j = test(i);
if(j != 0xDEAD)
{
printf("%0x\n" ,j);

}
}

F:\Borland\BCC55\MYCRAP~1>


compile it with bcc32 -v

Code:

F:\Borland\BCC55\MYCRAP~1>bcc32 -v myFisrtCrapExp.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
myFisrtCrapExp.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

F:\Borland\BCC55\MYCRAP~1>


and fire up ollydbg with
Code:


F:\Borland\BCC55\MYCRAP~1> f:\odbg110\OLLYDBG.EXE f:\Borland\BCC55\mycrapexps\my
FisrtCrapExp.exe



if you have the right settings in ollydbg viz
Code:

options -> debugging options -> events --> make first pause at radio button selection at WinMain (if location is known )

Question
what other two are and where do they stop ?


ollydbg will automatically go to your main
like

Code:

00401167 myFisrtC.main PUSH EBP
00401168 MOV EBP, ESP
0040116A PUSH EBX
0040116B MOV EBX, 3
00401170 PUSH myFisrtC.0040A128 ; /format = "My First Crap Experiment with bcc 5.5 and ollydbg for Source level Debugging
"
00401175 CALL myFisrtC.___org_printf ; \___org_printf



you want source side by side ? toggle the comment bar at the top
if your bar isnt visible

right click -> appearance -> showbar
now toggle the comment to cycle through source , profile , and comments

here is a pic to make you believe

ant
June 25th, 2008, 14:14
With Borland C++ i tried the same code you've used.

C:\mysource>bcc32 myc.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
myc.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
C:\mysource>myc
My Experiment with bcc 5.5 and OllyDbg for Source level Debugging
dead1e55

Opened myc.exe in Ollydebugger - ->options --> debugging options --> events and i selected *winmain radio button.
Other 2 buttons seen here are *system break point and *entry point of main module.

Code:
" OllyDbg will automatically go to your main like "

00401167 myFisrtC.main PUSH EBP
00401168 MOV EBP, ESP
0040116A PUSH EBX
0040116B MOV EBX, 3

In my case it is it goes to:
00401000 > $ /EB 10 JMP SHORT myc.00401012
00401002 |66 DB 66 ; CHAR 'f'
00401003 |62 DB 62 ; CHAR 'b'
00401004 |3A DB 3A ; CHAR ':'

Code:
" Toggle the comment to cycle through source , profile , and comments "

Source or profile information are just blank for me but only comments are available.

How do i get that info of source as shown by you in the screen shot of Ollydebugger?????

bilbo
June 25th, 2008, 23:16
jackall
have a look at http://www.ethicalhacker.net/content/view/165/2/
it shows the same runtime of your program at the same address, and how to proceed with olly

Quote:
[Originally Posted by Polaris]
That code is rather typical output for MinGW

you're right, it is Dev-C++ based on MinGW

By the way, the runtime show us an interesting function found in Microsoft MSVCRT.DLL which is not documented at all

Code:

void __getmainargs(int *p_argc, char ***p_argv, char ***p_environ, int globbing, STARTUPINFO *p_startup);


Regards, bilbo

JMI
June 25th, 2008, 23:29
bilbo:

Good to see you back. Don't stay away so long.

Regards,

dELTA
June 26th, 2008, 06:57
Damn, bilbo is back! Had a long and successful journey though Middle Earth? Any nice tales to tell about it?

Welcome back indeed anyway! Will you be hanging around here some more again now?

blabberer
June 26th, 2008, 10:47
Quote:
[Originally Posted by ant;75403]With Borland C++ i tried the same code you've used.

C:\mysource>bcc32 myc.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
myc.c:

How do i get that info of source as shown by you in the screen shot of Ollydebugger?????



by reading my post a bit more carefully and by not missing some important things in my post

ant
June 26th, 2008, 12:01
Code:
by reading my post a bit more carefully and by not missing some important things in my post


iam sorry for not concentrating enough and i missed the (-v) earlier. It looks just great now with the appearence of source.

many thanks .

naides
June 26th, 2008, 14:16
That is what fucking enrage me with programming. Just like my wife, computers are very picky about little details: a -v

bilbo
June 26th, 2008, 23:20
JMI, dELTA,
happy to meet you again
Quote:
[Originally Posted by dELTA]Will you be hanging around here some more again now?

as long as my friend, Wizard Gandalf the Grey, will not call me away for more adventures...
My best regards, bilbo

dELTA
June 27th, 2008, 14:37
Nice to hear that bilbo. Again, welcome back.

forgot
June 28th, 2008, 13:11
Quote:
[Originally Posted by ant;75368]Is it advisable to use IDA Pro disassembler by a beginner ?????


if with hexray plugin

SiGiNT
July 8th, 2008, 14:22
Wel, I'll be damned, been wondering where the Frodo clan was, welcome back Mr. Biggins, (or Belladonna),- tell Gandalf to bug off!

Now to the subject, I used w32dasm for about a year until someone pointed out that it's easier to reverse with a REAL tool I would suggest keeping both around - occasionally the associated resource string in W32 is handy and correct. IDA is indispensible for .net ARM and all the other odd stuff.

SiGiNT

JMI
July 8th, 2008, 14:39
Small correction of a literary nature. It is the "Baggins" Clan, of which Frodo is a member. At last report, Frodo did not have his own Clan.

And I am afraid you will have to tell Gandolf to "bug off" on your own, and take the risk, yourself, of provoking his ire.

Regards,