PDA

View Full Version : Code running before entry point


live_dont_exist
October 6th, 2011, 02:33
Hi All,
I was trying my hand at a challenge posted by Eset on their site. Some parts I managed to solve but am now stuck. I will try and describe the problem:

--- There is some code which is running (somewhere) which is causing a blank CMD window to pop up even before the entry point of the program(as given by Olly). While stepping through this program, text is continuously written to the console window using WriteConsole and a congratulations message pops up when you pass a stage. I got past 1 stage. The next stage however just writes some garbage text to the screen(mostly encrypted somehow by some routine) and I don't know how to proceed.

--- I did some tracing backward and found that the address where this encrypted text is stored is populated even before entry point. So for e.g 4044AC has all the encrypted text. If I 'Follow in Dump' even before I start debugging, I can see this text is already present there in an encrypted form. Also there is this blank CMD window which pops up from somewhere; even before debugging starts...dunno how. There is some text called THiddenRecord also around there somewhere but I can't make any sense of it either.

--- I read about TLS callbacks and tried to use IDA to locate the same by following some posts online but there do not seem to be any TLS callbacks here.

--- I stopped at System Breakpoint but that did not help either. tried setting a Hardware breakpoint on the start of the encrypted text, but that didn't work either(maybe because it happens before)

--- One last interesting point is that running the executable using PEID to try and detect an entry point works. As in, PEID does say the entry point is different after Unpacking. However dumping the process from that new entry point using a plugin in Olly does not seem to work (with and without import table reconstructed) and the EXE crashes. So I continued working with the packed form.

I have attached 3 screenshots which I feel are relevant. The key point is 'How do things run before entry point'? Apart from TLS callbacks. Do I need to use a Kernel debugger now? :-o

Any pointers, good reads on how to proceed will help.

Thanks
Arvind

blabberer
October 6th, 2011, 15:55
any console app always pops up a cmd window

try compiling this and loading the exe into ollydbg and you will see a blank cmd window popping up

Code:

#include <stdio.h>
int main (void)
{
printf("Hello Iam A Console App\nopen me in ollydbg and i Will pop Up A blank cm
d Window\n";
}



as to that chall iirc it should resolve into a website address from where you can download level 2 challenge

Code:

******************************************************************************

Press [ENTER] to continue.1234567890
Congratulations. All seems to be done well. Continue with the next part of the c
hallenge here: **************************************************************************
***/eset_reversing_challenge_2.exe
End of the program.


as far as exe is concerned tls callbacks run before entry point
if the exe links to a Dll DllInit in that dll also Runs Before Entry Point Apart From Tls Callbacks

live_dont_exist
October 6th, 2011, 23:03
As usual..thanks a lot blabberer . So the CMD popping up is completely harmless then if its a console app and there is no TLS callback? Is that a correct assumption to make? Or are there other funny places from where code can run prior to entry point?

Wrt the challenge, do you remember if you had to patch the EXE at all? Coz I had to patch 1 JMP to get to the 'Congratulations message' .. maybe that is why the text is still encrypted and there is no URL as you say there should be . There was a series of GetLastError calls and funny comparisons to error codes that I felt could never be generated at all .. like 'This cannot run in a Full screen' ... and no way (AFAIK) to get past those.. so I patched.

And there is only 1 XREF to the Congratulations message which is triggered only if you go through all those GetError calls successfully...which I cannot for the life of me understand how it is possible. Any tips?

Arvind

blabberer
October 7th, 2011, 08:29
Quote:

if its a console app and there is no TLS callback


do you mean that if it is a console app then it will not have tls callbacks ??
if so that is a wrong assumption

Thread Local Storage has nothing to do with an app being console or gui

Every process (~99 % of processes ) will have at-least one thread and if there is a thread it can aspire to have its own local storage and its own local storage callbacks

i don't patch normally in its classic sense i simply flip-flop flags when i want to know whats on the other end of the fork

iirc i had to flip flop 4 times

the garbage is not because of the patch it is because of a debugger detection method that you missed look a bit deeper
to find an unrolled debugger detection and a xorring routine that depends on the outcome of the debugger detection routine

also in the patch path you mention there is a hint which says what the first letter in the undecrypted string must be

if you notice it looks for 0x68 or 'h'

find out how the garbage can start with 'h' and the garbage will be resolved to an address automatically

live_dont_exist
October 7th, 2011, 09:17
No No thats not what I meant..sorry for being unclear. I was asking... apart from TLS callbacks... and DLLInits which you mentioned.. are there any other ways to run code before Startup? Are there any good reads for all these methods?

Yes, stepping through is fine...I just patched it coz I didnt want to click the Z flag so many times each time

There were 2 anti debugging mechanisms I saw and managed to bypass:

a) It was checking for the presence of IDA temp files
b) It was checking if the Process listing had a list of debuggers and system monitoring tools.. had to close everything and rename Olly to get past this .. after which all my Olly plugins failed to load

There's one more?? Do normal pieces of malware also have so many?

On the challenge...I saw the CMP AX,68 yes... but didn't think on those lines...that it was a hint for a new URL http:/// . I will relook the challenge..thanks for your help..

Arvind

blabberer
October 7th, 2011, 16:30
Quote:

are there any other ways to run code before Startup


there are certain edge cases like c++ static constructors but wide implementation i haven't seen

Quote:

Do normal pieces of malware also have so many?


jerry the malware rat needs to be leaner and meaner and must have a lot of holes to come out from and set afire the tail of tom the debuggers and get lost before tom even gets a clue let alone douse the fire

i can surmise a few that are employed

trapflag
debug register contents dr7

is debugged using api legally
is debugged using peb and parsing structure offsets
chkremotedbg api

looking for ntglobal flag contents again peb parsing
heap flags ditto
force flags ditto

using fpu rounding errors on trignometric functions CIacos CiAsin etc
get last error variations on certain class of api calls those that have SeDebugprivilege aware results
int 2d int 2c int2e behaviors
timing delays using rdtsc , queryperf apis , time apis

internal ntdll functions like queryprocess info for debugport , ThreadHide

unhandled exception filters

playing with context , seh frame , return address etc in exception handlers

the above are classic pc debugger detection
if you are on vm some other things that are vm specific exist too
like using sidt instruction , blue pill , redpill, and other pill opposing pills
finding certain strings
using certain opcodes that should normally create a gpf not creating gpfs
looking for certain emulations like motherboard name for vpc iirc
vmware backdoor strings


this is not an exhaustive list


Quote:


that it was a hint for a new URL http:///


Wrong Assumption (never assume assume = ass of u and me )
i said h not http so you should be prepared to look for hippopotamus or hairy vampires
do not confine yourself to http:\\

Indy
October 7th, 2011, 19:49
Add module in the static import(DllMain()).

xsk
December 3rd, 2011, 14:28
Quote:
[Originally Posted by live_dont_exist;91180]Hi All,
--- I read about TLS callbacks and tried to use IDA to locate the same by following some posts online but there do not seem to be any TLS callbacks here.


The problem I have with this statement is that IDA is a non-ideal tool to make this determination. You should be using something like PEView or CFF Explorer in order to look at the raw data for the file, to see if there is a TLS RVA, and if so, if there is an associated TLS function pointer. More about TLS (and the PE binary format in general) can be learned in part 2 of the slides here: http://OpenSecurityTraining.info/LifeOfBinaries.html

edit: yeah, I just downloaded the eset challenge, and it took all of 30 seconds to confirm with PEView that it has a non-zero TLS entry in the optional header

live_dont_exist
December 4th, 2011, 00:02
Thanks xsk. I'll explore those other tools as well and post back here.

I read these posts on IDA to come to that conclusion.
http://isc.sans.edu/diary.html?storyid=6655
http://www.hexblog.com/?p=9

Why do you say though that IDA is not good enough for this purpose? Is it out of experience of analyzing a lot of malware and finding TLS callbacks that IDA did not detect... or is there a good read that I can read through somewhere that describes why?

Thanks
Arvind

xsk
December 4th, 2011, 08:23
Quote:
[Originally Posted by live_dont_exist;91485]
Why do you say though that IDA is not good enough for this purpose? Is it out of experience of analyzing a lot of malware and finding TLS callbacks that IDA did not detect... or is there a good read that I can read through somewhere that describes why?


I'm only saying that because it's trying to do the interpretation of the TLS information for you. Whenever something is trying to do the interpretation for you, it is subject to errors, or your misinterpretation of its results. It is much better to know how to do the interpretation yourself, and then look at the raw data in something which is trying to do minimal interpretation, like PEView. That's why I posted to my material covering the PE format, so you can learn how to do the interpretation yourself. You can even download the slides, figure out where the content is, and then skip to that location in the video of my class.

Xeno

live_dont_exist
December 4th, 2011, 08:31
Yes thank you.

I will download the materials and study them offline. Big kudos to you for taking the time to make such a lot available to everyone

live_dont_exist
December 30th, 2011, 01:25
Quote:
[Originally Posted by blabberer;91186]

the garbage is not because of the patch it is because of a debugger detection method that you missed look a bit deeper
to find an unrolled debugger detection and a xorring routine that depends on the outcome of the debugger detection routine

also in the patch path you mention there is a hint which says what the first letter in the undecrypted string must be

if you notice it looks for 0x68 or 'h'

find out how the garbage can start with 'h' and the garbage will be resolved to an address automatically


I took this up again today. If you still remember this challenge; a hint would be great. So here is what has happened now:

---- The encrypted text is present in a location even before entry point !!! It is just copied later. 4044ac is the exact location.
---- I looked for TLS callbacks as xsk suggested using PEView. Sure enough there is a TLS header but when I go to the callback address it is all junk code . Maybe a hint lies here?
---- The encrypted text starts with 's' but a compare happens with 'h' - so I was thinking of a direct XOR but XORing some bits do not make sense. That means there is some algo.. but on drilling down it seems like a simple copy from 4044ac.

So I am saying... a decision does not seem to be made HERE..but somewhere else and I am not able to find where. I tried playing with various JA , JE loops but either get the encrypted text or a 'Too close' message

I came this far:
--- The XOR routine you talk about is between 404565 and 404595...here the encrypted text is xored etc etc and converted to some weirder text.
--- There's a JLE above that but jumping over it goes to the too close message; that means its something else
--- There is an anti debugger comparison against running processes, then a bunch of fake GetLastError and then its this bit and what I said above. Cannot find anything else ... I keep hitting the XOR routine which plays around with the encrypted text.... that's all... maybe its something inside this? I keep expecting the next address to display on the console...and it just displays junk.

Any help is much appreciated..at least on how to think... n find this unrolled debugger detection.

Thnx
Arvind

blabberer
December 30th, 2011, 06:07
there is a byte which plays a role in the xor routine find out references to the byte all the references are related to debugger detection

live_dont_exist
December 30th, 2011, 06:23
Thanks. Just before I saw this though I had gone up on the site and saw they had put up solutions. When I compared the winning solution with what I had done...it turned out I missed a silly thing.

I had not reckoned with the 'IsDebuggerPresent' kind of feature that was part of the executable. Since I had renamed Olly all my plugins stopped working so read up a bit on how to truck the debugger into thinking that the program is not being debugged. Some posts later I found that EBX contains this state for some reason.

Followed EBX in dump...changed 3rd byte to 0... repeated all my other bypassing n patching steps and I finally got the URL . Now I will start Stage 2 which is apparently much harder.

1 thing which I would like to know is... why does EBX contain the address which explains if the exe is running in a debugger? Is EBX 'meant' for this? As in... I know EAX is used for return values...ECX for counters...is there anything similar for EBX?

Thank you for all your help.

blabberer
December 30th, 2011, 09:39
i dont remember any ebx the byte i was talking is somewhere at 409XXX range

this byte is modified after passing or failing Detection tricks

since you cheated and saw results ill post the check you probably missed

it might look like in pseudo code like this

mov r32, fs:[18]
mov r32 , [r32+30]
mov r32, [r32+2]
cmp r32,Const
if eq mov r32,OkByte
else mov r32,notok byte

now on returning from this function the ok / not ok byte is added to the constant at 0x409XXX
which in turn will effect the secryption

btw ollydbg's pseudo searching with one of the lines i post above will get you the unrolled detection snippet very easily

just right click ->search for --> all commands --> type lets say mov r32,[r32+30] or type mov r32,fs:[18] and hit ok and double click on the reference

live_dont_exist
December 30th, 2011, 09:49
Thanks. You're right about the byte. Its at 409b10 or something and its compared with 0. If equal jumps to goodboy else badboy. That much I got. The problem though was that it would never become 0 at all irrespective of what I did.

These protections I could bypass:
--- IDA Temp files
--- Running debugger Process detection
--- Patching to avoid GetLastError problems

But all this still resulted in encrypted junk. Then I looked at the solution.

Solution had:
--- Check for IsDebuggerPresent
--- IDA Temp files
--- Running debugger Process detection
--- Patching to avoid GetLastError problems

That was the extra thing I was missing. To solve this; I did the following:
--- Ctrl+F2
--- Right click on EBX - Follow in dump
--- Change 00 00 01 to 00 00 00
--- IDA Temp files
--- Running debugger Process detection
--- Patching to avoid GetLastError problems

After doing this the 409xxx byte automatically became 0 and I jumped to goodboy without the routine you are mentioning. Hope it is clearer now.

Thanks
Arvind

blabberer
December 30th, 2011, 12:35
Code:

004045D4 MOV EAX, DWORD PTR FS:[18]
004045DB MOV EAX, DWORD PTR DS:[EAX+30]
004045DE MOVZX EAX, BYTE PTR DS:[EAX+2]
004045E2 CMP EAX, 1
004045E5 JNZ SHORT eset_rev.004045ED
004045E7 MOV EAX, 80
004045EC RETN
004045ED MOV EAX, 1
004045F2 RETN



Code:

00408326 E8 A9C2FFFF CALL eset_rev.004045D4
0040832B 0005 AC904000 ADD BYTE PTR DS:[4090AC], AL


the byte at 4090ac will be 0x03 to start with and after successfully passing all detection methods will be 0x0a

this byte is passed as an argument to the xorring routine

Code:

00408487 ADD BYTE PTR DS:[4090AC], 4
0040848E MOV AL, BYTE PTR DS:[4090AC]
00408493 PUSH EAX ; /Arg2 = 00901240
00408494 PUSH eset_rev.004090AD ; |Arg1 = 004090AD
00408499 CALL eset_rev.0040453C ; \eset_rev.0040453C



and this byte is used in the xorring routine here
Code:

0040456F |MOV CL, BYTE PTR SS:[EBP+C]



this is how your analysis should be
i dont know why you need to restart (ctrl+f2) i think after restarting ebx holds a pointer to !peb if so then you are patching !peb->IsbeingDebugged (this is fine but this is not the way to do analysis it simply means you use some cheat to pass hurdles and do not understand the underlying mechanism) and many plugins will do this automatically for you

restart from start and re analyze the program and understand the mechanisms so that next time you dont have to look for cheats when one of the cheats stops working
you can create your own cheats everytime


edit
i reran to check your comment about 409b10 it is not a byte it is a dword
a byte is only 8 bits
a word is only 16bits
a dword is 32 bits
2 bytes = 1 word
2word / 4 bytes = 1 dword
when i said byte i meant byte not a dword
and the dword at 409b10 is a checksum of the decrypted string it should be equal to 21b6 (that is another hint you could have worked backwards from)
like ineed 21b6
so to have 21b6 from the preceding algo what should i do
also it checks for h at start
to get h what should i do

you know itis a xor and xor is reversible so to get h as start you should know what cl must be
so for cl to be the required byte what must be the preceding requirement etc

reversing is a methodical approach

live_dont_exist
December 31st, 2011, 01:31
Yes Thanks. I got it now. I redid the part where I was patching EBX after reading your post. It much more logical that way and I don't have to "guess" what protection there is and change the PEB value without understanding. In fact the IsDebuggerPresent function also is not called; if it was that would also be a clue. Since it isn't I guess this is the best way.

I have a question though...At what point would 1 realise that the byte at 4090ac is deciding a lot of things? Its when I step through and finally reach the XOR routine at the end..rt? And then i put a hardware breakpoint on 4090AC to break on Access... then restart the program and see where all it is being accessed and why and work from there..trying to identify the various antidebug measures. So for e.g
Code:

00408487 ADD BYTE PTR DS:[4090AC], 4
0040848E MOV AL, BYTE PTR DS:[4090AC]
00408493 PUSH EAX ; /Arg2 = 00901240
00408494 PUSH eset_rev.004090AD ; |Arg1 = 004090AD
00408499 CALL eset_rev.0040453C ; \eset_rev.0040453C


I would have to arrive at 40848E to even understand that 4090AC is important. Otherwise it would be difficult to understand anything. Am I correct?

Then following that logic it's now clear that 4090AC starts with 03.
--- It is incremented by 1 at 40832B (For IsDebuggerPresent)
--- It is incremented by 2 more at 408431 (For IDA Temp files and Running process checks)
--- Then I patch the 5 GetLastError's
--- Finally it is incremented by 4 at 408487
--- The sum comes out to 03+01+02+04=0A !! ---> Just like you said

This is also passed as an argument to 40453C and an XOR happens with the garbage text at 901240 etc etc resulting in the final URL.

Just 1 thing I will slightly disagree on is that it's not a straight XOR with 0A. Its some minor addition and shifting before the XOR happens. So for e.g 0A becomes 1B before XOR of the 1st byte. So the algo ..instead of : Encrypted Byte 1 XOR 0A becomes Encrypted Byte 1 XOR MinorChanges(0A) instead. But yes.. its quite trivial and understandable easily.

The only thing is that I'm not great at math so try and make the program do the math for me wherever it is instead of trying to understand the algo in depth..that's a problem I hope to overcome slowly by reversing more.

But this makes so much sense now... thanks for your help

---------------
Edit:
I looked at 4090b1 as well and found how to work with that as well. The initial value is set to 21B6 as you said. The XOR routine if it calculates correctly returns 21B6 in EAX. Value of EAX is subtracted and it becomes 0 and then a CMP 4090b1,0 goes to goodboy.

Also checked that 4090b1 is not used anywhere else but only at the end by Right Click - Search For - All constants - 4090B1 ..only 2 references right at the end pop up . Lots of nice tricks and learning lots..thnx

blabberer
December 31st, 2011, 09:04
Quote:

I have a question though...At what point would 1 realise that the byte at 4090ac is deciding a lot of things


you can realize that byte may play a role immediately on returning from the isDebuggerPresent Routine

Code:

00408326 CALL <eset_rev.IsDebuggerPresent>
0040832B ADD BYTE PTR DS:[4090AC], AL



Code:

004045D4 <>MOV EAX, DWORD PTR FS:[18] ; nt_teb -> self ptr
004045DB MOV EAX, DWORD PTR DS:[EAX+30] ; PEB
004045DE MOVZX EAX, BYTE PTR DS:[EAX+2] ; nt!_teb ProcessEnvironmentBlock->BeingDebugged
004045E2 CMP EAX, 1
004045E5 JNZ SHORT eset_rev.004045ED
004045E7 MOV EAX, 80 ; if debugged retn 0x80
004045EC RETN
004045ED MOV EAX, 1 ; if not debugged retn 1
004045F2 RETN


and you can find references to that byte immediately and set bp immediately
Code:

References in eset_rev: to 004090AC
Address Disassembly Comment
00404BCF MOV EAX, eset_rev.004090AC 004090AC=eset_rev.004090AC
0040832B ADD BYTE PTR DS:[4090AC], AL (Initial CPU selection)
00408414 ADD BYTE PTR DS:[4090AC], 20 DS:[004090AC]=03
00408431 ADD BYTE PTR DS:[4090AC], AL
00408487 ADD BYTE PTR DS:[4090AC], 4 DS:[004090AC]=03
0040848E MOV AL, BYTE PTR DS:[4090AC] [004090AC]=03