Archive for the ‘IDA-Pro’ Category

# try to attach to me… if you can!

why we might want to attach to active process? there are zillion reasons to do it. for example, the file is packed and stuffed with many adbg tricks. or, maybe, we found a suspicious process in memory and want to analyze it. maybe something else…

there many ways to prevent attaching: self-replicated and self-debugged processes do it very well, but there is another way. please, download the crack-me (with sources) and try to handle it by yourself.

  • 1) run to_attach_31.exe;
  • 2) run OllyDbg or IDA-Pro;
  • 3) try to attach the debugger to the process;
  • 4.1) in Olly: File => Attach => to_attach_31.exe;
  • 4.2) in IDA: Debug => Attach to process => to_attach_31.exe;
  • 5) see “shit happens” messages;
  • 6) the process is still running and the debugger has no control;
Olly is unable to attach to the process

Olly is unable to attach to the process

well, how it worked? when debugger is attaching to process, a new thread is created. NTDLL!DbgBreakPoint function is called and it’s called by not-exported KERNEL32!_BaseAttachComplete@4. the problem is that the thread is created inside the debugged process, so the debugged process can change NTDLL!DbgBreakPoint. for example, intercept it and terminate the system thread preventing attaching. or… abuse the debugger! why not?! we can do almost everything, including creating a faked thread and attaching the debugger to it!
see the source code.

p = (DWORD) GetProcAddress(LoadLibrary(“NTDLL.DLL”), “DbgBreakPoint”);

// nasty dirty trick – we just overwrite the code of DbgBreakPoint
VirtualProtect(p, 1024, PAGE_EXECUTE_READWRITE, &old);
jmp inject
x_code: mov eax, offset souriz
jmp eax
inject: mov esi, offset x_code
mov edi, p
mov ecx, 2

the code above patches NTDLL!DbgBreakPoint, injecting mov eax, offset souriz/jmp eax code over it. not good! but it’s just a POC after all, so feel free to improve it. anyway it woks!

I tested it under: W2K SP4, XP SP3, S2K3 SP1. please, test the crack-me under other systems. a few people reported that MsgBox, called by souriz() function not appears on the screen. it’s strange. I have no idea why – need more info to find out.

the last question is: how to bypass this trick? I think, the best strategy – just to check NTDLL/KERNEL32 before attaching (via ReadProcessMemory) and restore them if it’s necessary, but… it’s possible to prevent attaching, changing only data and the second problem: in real life we want to know what the program changed exactly. will think how to handle it.

P.S. see comments for more details.


# IDA-Pro 5.4: old bugs on the new streets (was: to download or to not download)

IDA-Pro 5.4 has been released. aside of many positive changes it’s just a huge bug-fix. take the old bug with zero-based PE-files for example. I reported it to Ilfak long before 5.3. now it’s fixed and following pictures taken by Elias Bachaalany (the clever guy working for hex-rays) proves it.
not good for me, coz I was going to talk about it (and many other IDA-Pro bugs) on Code Gate 2009 security conference in South Korea . well, never mind. I have enough time to redesign my syllabus

dead bug

dead bug

TLS flooding bug (also discovered by nezumi) has not been fixed yet. um, going to write a short article how to fix it with _your_ hands.


# PatchDiff => Hex-Rays => WinDiff: the way to analyze patches faster

as a reverser working for Endeavor Security, Inc nezumi gets used to analyze zillions security patches and, like many other reversers, its hard tool is Patch-Diff (free analogue of commercial Bin-Diff). Patch-Diff is great, but… too graphical (don’t like gui stuff very much, nezumi loves cheese and console).

too hard to trace there wires

too hard to trace there wires

Patch-Diff works good if there are just a few changes, but dealing with a totally rewritten function driving me bats and takes too much time. these graphs… oh… well, nezumi has came to much better solution.

1) use Patch-Diff or Bin-Diff to find matched function(s);
2) ask Hex-Rays to decompile them into high-level C-code;
3) compare patched and un-patched C-code with WinDiff or GNU diff3;

it’s works! but… there is a problem. guess, patched function has more local vars, so the stack frame is completely different from the old one, so, Hex-Rays gives different names to the same variables!!! thus, WinDiff goes crazy and shows many false positive unmatched lines.

what we’re going to do? well… Hex-Rays is an interactive decompiler (View/Open Sub-view/Opcode or F5), so it’s possible (and not too hard!) to rename variables, I mean to synchronize them. it takes time, but it’s definitely worth what it costs!!!

this trick helped me to analyze MS09-01 patch extremely fast. of course, right now, it’s just a pure idea, but I’m going to improve it.

btw, does anybody know the best tool for smarting comparing C-sources? plz, write me back ( or leave comment here.


# Baghdad – dead alive breakpoints

not Baghdad actually, just Borland stuff. it’s russian jargon. borland => baghdad (they sound quite similar). well, you want to hack a Baghdad program? and breakpoints do not help you to hack it fast? well, guys…

set breakpoints on library functions. IDA-Pro recognizes them and once they have been recognized and addresses determined – feel free to use any debugger – Olly or Soft-Ice.

the most interested functions are listed bellow (of course, the list is incomplete, just gives you an idea what to do):

@TControl@GetText$qqrv ; TControl::GetText(void)
@System@@LStrCmp$qqrv ; System::__linkproc__ LStrCmp(void)
@Sysutils@Now$qqrv ; Sysutils::Now(void)
@Sysutils@DecodeTime$qqr16System@TDateTimerust2t2t2 ;; Sysutils::DecodeTime(System::TDateTime,ushort &,ushort &,ushort &,ushort &)
@Sysutils@StrToInt$qqrx17System@AnsiString ; Sysutils::StrToInt(System::AnsiString)
@Controls@TControl@SetVisible$qqro ; Controls::TControl::SetVisible(bool)
@Controls@TControl@SetText$qqrx17System@AnsiString ; Controls::TControl::SetText(System::AnsiString)
@Mask@TCustomMaskEdit@GetText$qqrv ; Mask::TCustomMaskEdit::GetText(void)

btw, there is a good plugin for Olly – GoDup (by godfather+) allowing to use IDA-Pro signatures directly.


# dynamic TLS callbacks instead of SEH

static TLS are not static at all! actually, they’re dynamic. statically declared TLS could be changed in run-time without using any API. it’s possible to register/unregistered new TLS callbacks on the fly even after the file has been loaded.

it was a long story – I tried to found where OS keeps TLS info, but was unable to do it. suddenly something hit me – maybe OS does not keep TLS info at all? maybe OS reads PE file directly? quick investigation confirmed this suggestion. as a matter of fact: OS re-reads PE-header and .tls every time it need the data.

on any following even DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH Windows NT reads Data Directories -> TLS Directory. if VirtualAddress isn’t zero, OS reads Address of Callbacks Array and executes the first callback in the list. after it, OS reads the next element of Address of Callbacks Array.

what does it mean? it means: a) we can add/remove new TLS callbacks from another TLS callback or the program; b) if TLS Directory does not fit our needs it’s possible to create the new one on the fly;

guess, we have a program with statically declared TLS callbacks or without TLS at all. the program changes TLS array or creates it from the scratch. how interesting and how useful for malware!

shell-codes and malware sometimes make errors leading to exceptions. not good! thus, malware uses SEH to intercept expectations and suppress them. it was easy. “was” because SafeSEH mechanism has been infixed. too bad for hackers! well, what’s about TLS? if TLS data or TLS callback array belongs to writable memory – no problem to change it on the fly. as it was mentioned before, any exception generated by TLS is suppressed by OS. so, we got what we want.

moreover. guess, a hacker attacking an application, does something wrong and the application crashes. OS terminates it, Dr. Wantons saves the log for future analysis. quite common scenario, isn’t? well, dynamic TLS callbacks is absolute differing thing. TLS callback is called after the critical error, but _before_ process will be finished. in other words, malicious code inside TLS callbacks will be called _after_ Dr. Watson have finished loggin!!!

another thing. add new TLS callback (or create TLS Dir from the scratch), raise an exception (kind of XOR EAX, EAX/MOV EAX, [EAX]) and… pass control to TLS. of course, critical message will appear, but… not every reverser will find out where control is passed after pressing “OK” key.

no matter how TLS info is changed, it might be a local process or something else. yes, it’s possible to add new callback to another process, using WriteProcessMemory.

to demonstrate this I wrote a simple test program adding TLS callback on the fly. download it and run. if you speaker makes “buzz” before and after Message Box it means the program works fine. otherwise: either you have no speaker, either something wrong.

source code is very simple. see it bellow:

BOOL WINAPI TLS_callback_01(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
BOOL WINAPI TLS_callback_02(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);

// TLS callback_01 is declared statically
// TLS callback_02 is not declared yet (will be added dynamically)
DWORD ptr[] = { (DWORD) TLS_callback_01, 0, 0 };
DWORD *xl[] = { (DWORD*) 0xEFBEADDE, ptr, ptr, (DWORD*) xl, ptr, 0, 0};

// this callback is declared statically
BOOL WINAPI TLS_callback_01(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
// add new call-back
if (fdwReason == 1) ptr[1] = (DWORD) TLS_callback_02;
return 0×666;

// this callback is not declared statically, will be added dynamically
BOOL WINAPI TLS_callback_02(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
// make sound
Beep(96, 6000); return 0×999;

// main function, just to be
nezumi() { MessageBox(0, “press ok to hear buzz”, “[x]“, 0); }


# IDA-Pro and simple (E)SP hack

it’s rather a dirty hack than anti-IDA trick, but… it’s quite interesting to be described. as far as we all know, IDA-Pro traces ESP register to reconstruct local variables layout. of course, it’s easy to abuse that mechanism. the tracer emulates very restricted set of CPU commands, however, we want to abuse not only IDA-Pro, but hackers as well. how we can do that?
consider the following example:

int a = 0xC0DE;
mov eax, a
add ebp, 4 ; // change EBP
mov eax, a ; // read memory outside var a
sub bp, 4 ; // change BP (not EBP!)
mov eax, a ; // read memory from… couldn’t really say

mov eax, [esp] ; // read some memory cell (B)
add esp, 4 ; // change ESP
mov eax, [esp] ; // read another memory cell (D)
sub sp, 4 ; // change SP (not ESP)
mov eax, [esp] ; // read memory from (B) or somewhere else

the point is: if LOWORD(ESP/EBP) < 0xFFC, the instruction "sub sp/bp, 4" restores the original value of the register. otherwise we accessing another memory cell. thus, behavior of mov eax, [esp/ebp] depends on ESP/EPB value. interesting!

what’s about IDA-Pro? let’s get IDA-Pro 5.3 and see it! download the compiled example and disassemble it:

mov [ebp+var_4], 0C0DEh
mov eax, [ebp+var_4]
add ebp, 4
mov eax, [ebp+var_4]
sub bp, 4
mov eax, [ebp+var_4]
mov eax, [esp+10h+var_10]
add esp, 4
mov eax, [esp+0Ch+var_C]
sub sp, 4
mov eax, [esp+10h+var_10]

IDA-Pro does not trace EBP at all! um, is she supposed to do it? IDA-Pro flattery tells us [ebp+var_4] and it means: trace EBP by yourself! thanks, IDA-Pro! we will do it! but what about ESP?

as we can see IDA-Pro traces ESP and knows that EP is part of ESP. wow! how clever! I mean how stupid! IDA-Pro totally forgets what’s part. in general case “(WORD) ( ((DWORD) a) + 4) – 4″ is not equal a. it might be the same, but might be different. depends on a. I would prefer to see honest “sp-analysis failed” than unreliable result.

it’s a bug of IDA-Pro. if 32-bit function changes SP she has to stop tracing if she is unable predict the result (and she is unable to do that)

do you want to make reversing harder? just change EBP somewhere in EBP-based function. reverses probably will not find out it fast, especially if it’s a huge function.


# TLS callbacks w/o USER32 (part II)

Peter Ferrie posted an interesting comment on my previous article. I decided to reply here, coz not everybody reads comments, but it’s discussion worth to be read.

Peter Ferrie> That’s not correct. You can’t display a message anymore from a TLS callback
Peter Ferrie> because USER32 is not initialised at that point,

I don’t try to display a message from TLS callback, I try do _not_ display it :)
XP SP3 and S2K3 allow me to call MessageBox form TLS, Vista does not, but I’m not talking about calling something from TLS. the point is – if there is no USER32, TLS isn’t called at all. check out FSC08_Level2.exe. it’s F-Secure’ crack-me, written by Kamil (very clever guy!), who packed a file with UPX and added TLS callback, thus “upx -d” loses the TLS. it’s easy and you probably noticed this. but you definitely missed the point. there is MSVCR71.dll!exit there that is imported, but not actually used. UPX does not use MSVCR71.dll, so it was added by someone else. guess it was Kamil :-) who added it manually. but for what’s reason? the answer is – without it XP and S2K3 refuse to call TLS. so, F-Secure guy met the bug and found the workaround. it proves that I’m right and the bug does exist :-)

Peter Ferrie> but it does really run. Create a TLS callback that looks like this:
Peter Ferrie> mov eax, dword ptr fs:[30h]
Peter Ferrie> l1: cmp byte ptr [eax + 2], 0
Peter Ferrie> je l1
Peter Ferrie> int 3
Peter Ferrie> and run it. The file will wait until the debugger attaches.
Peter Ferrie> That shows that the callback is running.

guess, your TLS callback is executed when the process is about the end, you don’t check for the reason argument. could you please show me your exe file? I show you mines. plz, download two examples. they are very simple:

#define Msg (int (WINAPI *)(int, char*, char*, int))
#define Box GetProcAddress(LoadLibrary(“USER32.DLL”),”MessageBoxA”)

#define TLS_B ” not”
#define TLS_C ” executed! *\n\n”
#define TLS_A “\n* TLS callback has been”

char TLS[] = TLS_A TLS_B TLS_C;

BOOL WINAPI TLS_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
if (fdwReason == 1) memmove(&TLS[sizeof(TLS_A)], &TLS[sizeof(TLS_A TLS_B)], sizeof(TLS_C));
return 0×666;

nezumi(){Msg Box (0, TLS, “[x]“, 0);}

DWORD ptr[] = { (DWORD) TLS_callback, 0 };
DWORD *xl[] = { (DWORD*) 0xEFBEADDE, ptr, ptr, (DWORD*) xl, ptr, 0, 0};

TLS callback just removes “not ” from the string displayed from the main functions. compile it, apply TLS Dir and run. under W2K TLS is executed, but it does not executed under XP/W2K3, however if you replace GetProcAddress(LoadLibrary(“USER32.DLL”),”MessageBoxA”) by a direct MessageBox call it will work fine.

btw, I found another interesting thing. run TLS-nousr.exe under Olly 1.10 (have not checked another ver) under XP/S2K3. ops! TLS callback is called. ok, run it under IDA-Pro debugger (console ver). wow! it’s not called! so, OllyDbg forces system to execute TLS somehow. have not found out how yet.


# another EnableTracing() bug

looks like IDA Pro 5.3 has another bug. EnableTracing()/GetDebuggerEvent(WFNE_ANY, -1); returns 10h (BREAKPOINT) on function calls thanks to internal IDA-Pro breakpoints. IDA-Pro sets breakpoints after calls to perform step over tracing (TRACE_FUNC). Soft-Ice and OllyDbg do the same thing. the problem is – EnableTracing() does it every time, even we ask it for TRACE_STEP or TRACE_INSN. IDA-Pro should hide internal breakpoints, but she forgets to do it!

not good for us! well, how we’re going to handle this? um, r_eip = GetEventEa() points to the next instruction after the call and GetBptAttr(r_eip, BPTATTR_EA) = = -1, where -1 means no breakpoint here. why? coz, GetBptAttr() hides internal breakpoints, but GetDebuggerEvent() does not. so, it’s definitely a bug. normally, debuggers always hides internal breakpoints – nobody wants to confuse users. well, IDA-Pro does.

another bug: a real breakpoint just freezes IDA-Pro and GetDebuggerEvent(WFNE_ANY, -1) will never return, so we have to specify the second argument (time to wait), calling the function like this: GetDebuggerEvent(WFNE_ANY, 0×3). of course, if GetDebuggerEvent() returns DBG_TIMEOUT we have to check for real breakpoints. if GetBptAttr(r_eip, BPTATTR_EA) = = r_eip it means that a real breakpoint is here. it’s a simple heuristic algorithm, but it works!

I wrote a simple script to demonstrate how to use EnableTracing(). download it and run. the output should look like this:

IDA says breakpoint:
00402CECh:call ds:HeapFree
00402CECh:pop esi

IDA says breakpoint:
00401AC4h:call _calloc
00401AC4h:pop ecx

IDA says breakpoint:
00401067h:call _printf
00401067h:add esp, 10h

4010B0: hit breakpoint
heuristic says breakpoint!

did you see this? IDA-Pro stops at every calls!!! so, the final version of the correct tracer should look like this:

// start tracing
EnableTracing(TRACE_XA, 1);

// wait for any debug even
code = GetDebuggerEvent(WFNE_ANY | WFNE_CONT, MAX_WAIT);

r_eip = GetEventEa(); // next even eip

if (code == BREAKPOINT) // <<< IDA BUG!!! Message("IDA says breakpoint:\n%08Xh:%s\n%08Xh:%s\n\n", r_eip, GetDisasm(PrevHead(r_eip, 0)), r_eip, GetDisasm(r_eip) ); if (code == DBG_TIMEOUT) // exit due to timeout { // check for breakpoints if (GetBptAttr(r_eip, BPTATTR_EA) == r_eip) // real bp Message("heuristic says breakpoint!\n"); break; } // check for errors if (code < 1) break; // wait for a next event // MAX_WAIT (time to wait, sec) - prevents IDA freezing code = GetDebuggerEvent(WFNE_ANY, MAX_WAIT); }


# IDA-Pro EnableTracing() – how not to do

Ilfak improved IDA-Pro scripting engine recently. many new functions were added. real gift for all script fans! the only problem is – the lack of documentations. it’s not easy to understand how to use these functions. take EnableTracing() for example. it’s very useful and powerful func, but… the way how it interacts with IDA-Pro debug engine is not trivial and involves GetDebuggerEvent(), GetEventEa() and other functions.

but we’re lucky! Ilfak polished a simple, but a very practicable script shows us how to unpack UPX with EnableTracing(). um, why we do need to trace an upxed program? it’s too slow. better to set hardware breakpoint on [ESP-4] and find the first jump after it. ok, never mind. it’s just EnableTracing() example. whatever.

the truth is – this is an example how do _not_ write scripts. I saw a few scripts based on this example. people just grabbed the code and rewrote it to fit their needs. please, do not do this unless you want to be fucked up. just look at this: (the mirror:

EnableTracing(TRACE_STEP, 1);
for ( code = GetDebuggerEvent(WFNE_ANY|WFNE_CONT, -1); // resume
code > 0;
code = GetDebuggerEvent(WFNE_ANY, -1) )
r_eip = GetEventEa();
if ( r_eip >= tea1 && r_eip < tea2 ) break; } if ( code <= 0 ) return Failed(code); ...

Ilfak does perform a lot of checks, but they are not quite correct and consequences are just terrible. dare to try? well, download, set breakpoint on 00409CCCh and run Ilfak’ script. IDA-Pro freezes. CTRL-BREAK does not work and we have to kill IDA-Pro process.

why it happens? well, if EnableTracing() meets a breakpoint it stops the process, but the script waits an even – GetDebuggerEvent(WFNE_ANY, -1) which will never happen, coz the process has been stopped.

how to fix the problem? well, it’s easy. just replace “(code > 0)” by “((code > 0) && (code != BREAKPOINT))” and “if ( r_eip >= tea1 && r_eip < tea2 ) break;" by "if ( r_eip >= tea1 && r_eip < tea2 ) { PauseProcess(); ... EnableTracing(TRACE_STEP, 0); break;}". it's still not good, but at least prevents IDA-Pro freezing on breakpoints. btw, don't forget about exceptions! you have to handle them as well. btw, CTRL-Break does not disable tracing, enabled by EnableTracing(). what’s a… um, a nasty bug! to disable tracing press CTRL-F2.


how powerful IDA Scripts might be

I spent all day trying to reverse a brutal protection, but was not succeed. well, I drank a cup of rasta-tea (it’s legal here) and wrote 5 lines IDA Script (2 lines were mines, 3 lines were stolen). it highlighted what I was looking for, it took less than a minute! this is the point! if something goes wrong – the approach is not good. there is a better way. somewhere. the only problem is to understand what we’re really want to get. in my case I just wrote an extreme simple profiler show how many times instructions are executed. this helped me to defeat obfuscated code almost immediately. it was a forth-like virtual machine. knowing frequency distribution it was easy to recognize the most popular and most unpopular constructions, like mov, cmp, etc. the code became readable even without decompiler :)