Log in

View Full Version : "call eax"; needle in the haystack


Rhythm
March 2nd, 2003, 17:32
Fellow reverse engineers,
I could use your thoughts on a protection scheme that i'm trying to understand. Before explaining the basic idea i'll give some background information on the protection scheme (license key check).
From a Java environment a JNI call is made to a subroutine in a native dll. The dll depends on other dll's of which two are well known, namely: mingwm10.dll (Thread safe exception handling over DLL exported functions) and zlib.dll (Data-compression library).
Another interesting fact is that the SoftICE symbol loader isn't able to load the exports, which makes me think the programmers know what they are doing (fun, fun, fun! :-) ). the function body in c would look like: "int check(String license)"
The licensecheck subroutine in the dll looks somewhat like this:

1 mov eax, "first four bytes of entered license key"
2 push license key, other variable
3 mov eax, [eax+2A4h]
4 call eax ; dynamic call

5 call subroutine-at-static-address

6 repeat 1-4 with [eax+2A8h]
7 return

the dll is loaded in the 68B3**** area, since B3 isn't a common ascii char i'm led to believe that the dynamic call is destined to fail.
agree so far? :-)

this fact and the fact that exception handling in the dll is possible made me write a little application loading the dll, getting the address of the function and make a call to the function. debugging this process results in a crash at [4]. remarkable because the application doesn't crash calling the same function, regardless the serial number.

my thought are that another thread from the dll is running and is waiting for an exception to be thrown at [4] or [5] and taking over? is this possible? or is it possible that the valid license key would conclude to a 'correct' jump to code outside the dll?

what is the best approach to tackle these scheme? i'm out of options. the dll didn't give me anymore usefull information as the facts stated above.

Thanks for helping out a new oldbie :-)

bzzt
March 2nd, 2003, 18:39
can you de comp ile the java class which contains the jni call.

maybe change to do what you want and replace.

something to at least look at.

Kayaker
March 2nd, 2003, 19:42
Hi new oldbie, heh, just a couple of ideas.. You say SoftICE symbol loader isn't able to load the exports - if you've correctly identified them for loading in winice.dat (or dynamically via sym loader) and they have been successfully loaded they should show up when you type 'EXP <partial name>' in Softice. You can confirm the correct exported name syntax to use for a breakpoint this way, or break on the loaded address directly.

I can't specifically think of an "anti-" code way to prevent SI from loading exports, but it's interesting if you found a method. If this still doesn't work, you can always hex edit the first byte of the exported function in the dll to 0CCh and set 'BPINT 3' in Softice (I think that's the trick), changing the bytes back when you break. Now you could type 'THREAD' in Softice and see if there is an extra thread running in your process as you suspected...

Sounds like an interesting protection in any case..

Kayaker

Rhythm
March 3rd, 2003, 05:11
About the symbol loading problems:
First of all i have no problem breaking into the dll. In my own controlled environment it's just a matter of breaking on LoadLibraryA or GetProcAddress and take the first call to the loaded function.

In detail:
When i load the dll in the symbol loader (v2.7.0 build 562) by selecting 'Load Exports...' the event window tells me that exports have been succesfully loaded. In the 'loaded symbols' window a new entry appears with the name of the dll and the status (not loaded). Refreshing the window results in a scrambled name for the displayed dll, refreshing a second time results in an empty name. Exports have not been loaded into SoftICE. Maybe this is because of the thread/exception code in the dll, maybe it's intentionally.

bzzt, decompilation doesn't do the trick, because license key checks are made from the dll (or other dll's) too. besides i'm more interested in the works of the registration scheme :-)

time to look into the 'thread' command of softice (didn't knew it existed :-) ). more input is always welcome!

xybyre
March 12th, 2003, 17:25
> the dll is loaded in the 68B3**** area, since B3 isn't a common ascii char i'm led to believe that the dynamic call is destined to fail.
> agree so far? :-)

I'm not sure what you mean by this. A DLL can be loaded anywhere in the process's memory space.

If you trace into the "call eax", you will probably find that it is always the same each time you run the program. If so, then it is not really a dynamic call. Does the callee change each time you run it?

The
mov eax, [eax+2A4h]
call eax ; dynamic call
may just be the compiler's way of resolving a virtual method pointer, or the programmer could be using a function pointer table.

> this fact and the fact that exception handling in the dll is possible made me write a little application loading the dll, getting the address of the function and make a call to the function. debugging this process results in a crash at [4]. remarkable because the application doesn't crash calling the same function, regardless the serial number.

Did you specify the right calling convention for the function? This has bitten me a few times. The DLL function could be declared as stdcall, cdecl, or WINAPI (aka Pascal), and if you don't declare (typedef) the exported function with the same calling convention, you will get a crash (or the function will work wrong because the parameters are out of order)

>my thought are that another thread from the dll is running and is waiting for an exception to be thrown at [4] or [5] and taking over? is this possible? or is it possible that the valid license key would conclude to a 'correct' jump to code outside the dll?

I am pretty sure that exception handlers have to be registered per-thread, so I don't think it's possible for another thread to jump in when an exception occurs. Furthermore, exception handlers are implemented differently by different compilers, so DLLs with exception handling enabled are not compatible across compilers. If you are calling the DLL function from code you've compiled with a different compiler, and the DLL function throws an exception, then that would explain why your program crashes.

Hope this helps!

Rhythm
March 13th, 2003, 06:05
helps a bunch, thank you!

.text:68B3D110 var_18 = byte ptr -18h ; String licenseKey
.text:68B3D110 arg_0 = dword ptr 8 ; ??
.text:68B3D110 arg_8 = dword ptr 10h ; ??
.text:68B3D110
.text:68B3D110 push ebp ; Java_***_checkLicenseKey (JNI call)
.text:68B3D111 mov ebp, esp
.text:68B3D113 sub esp, 0Ch
.text:68B3D116 push edi
.text:68B3D117 push esi
.text:68B3D118 push ebx
.text:68B3D119 mov ebx, [ebp+arg_0] ; address of licenseKey
.text:68B3D11C add esp, 0FFFFFFFCh
.text:68B3D11F mov eax, [ebx] ; move 4 bytes of LicenseKey in eax
.text:68B3D121 push 0
.text:68B3D123 mov edx, [ebp+arg_8]
.text:68B3D126 push edx
.text:68B3D127 push ebx
.text:68B3D128 mov eax, [eax+2A4h] *crash* illegal address
.text:68B3D12E call eax ; dynamic call
.text:68B3D130 mov edi, eax
.text:68B3D132 add esp, 4
.text:68B3D135 add esp, 0FFFFFFF4h
.text:68B3D138 push edi
.text:68B3D139 call sub_68B3E5F0

i've assumed the var to be the licenseKey, simply because the only native function is called with the licenseKey String. could this assumption been wrong? i haven't been able to break into the dll with softice in the programs environment, only in my own setup.

>Did you specify the right calling convention for the function? This has bitten me a few times. The DLL function could be declared as stdcall, cdecl, or WINAPI (aka Pascal), and if you don't declare (typedef) the exported function with the same calling convention, you will get a crash (or the function will work wrong because the parameters are out of order)

interesting, i used typedef ... and out of order parameters certainly would explain the crash! looking into it now ...

xybyre
March 13th, 2003, 11:33
I don't have enough code to say for sure, but looking at that code snippet, I would guess that you are interpreting the code incorrectly.

This is how I would interpret the code:
.text:68B3D119 mov ebx, [ebp+arg_0] ; get address of object
.text:68B3D11F mov eax, [ebx] ; dereference the pointer
.text:68B3D128 mov eax, [eax+2A4h] ; get address of method
.text:68B3D12E call eax ; method call

Since the function address called is calculated from the first parameter, I don't think it can be a string. I would guess that it is a pointer to a class object, and this code calls a method on that object.

Why can't you break into the code while the program is running? Can't you put a breakpoint on that address?

Rhythm
March 14th, 2003, 05:20
>Why can't you break into the code while the program is running? Can't you put a breakpoint on that address?

Lack of experience i guess (-:
this is what i've tried:
* symbol loading doesn't work (see first message), so i can't place a breakpoint on exported functions
* placing a bpx on bpm or bpr on/near the start of the function doesn't help.
* hwnd doesn't work; softice reports that there or no active dialogs. can't place a breakpoint on the windowhandle
* i can break on loadlibrarya and getprocaddress, the first doesn't bring me any closer, the second breaks a zillion times but not where i want it too break.
* making the breakpoint conditional so it only breaks when the pid is the pid of javaw.exe results in no breaking at all
* the bpint 3 trick doesn't work too, because i think the dll has some form of simple encryption. ida dissassembles the dll correctly, w32dasm fails after some time and hiew shows opcodes that don't belong there.

if anyone has some advice at how to break into the dll let me know, i'm out of options :-)

Rhythm
March 14th, 2003, 09:07
i've done some more puzzling. the dll has selfmodifying code. that's probably the reason why w32dasm and the symbolloader fail. the opcodes for the start of the routine are:
before modifying:
005589 *bogus add*
E583
EC
and after modifying:
55 push ebp
89E5 mov ebp, esp
83EC14 sub esp, 2Ch

hex-editing the 55 to CC gives me debugaccess ...
i'll keep you informed (-:

thanks for all the help so far!

dELTA
March 14th, 2003, 09:56
IF you look at those opcode bytes, you will see that they are exactly the same, except offsetted with one byte, which will cause the debugger/disassembler to interpret them differently.

If the code was really self-modifying, it would not work with inserting an int3, and neither would IDA be able to disassemble it, as you earlier stated it could.

Well, sure, if the "self-modification" consists of moving the code one byte forward or backward those two things are both theoretically possible, but that would be utterly stupid and unlikely. It would seem much more likely that your debugger/disassembler has just become misaligned with the opcodes in the first case.

Also, the code you presented is a typical function prologue, and it is very common that they have 00-bytes in front of them, for address alignment.

Check the addresses again. Are those two code-snippets really taken from the exact same adress, not one byte apart?

dELTA

Rhythm
March 16th, 2003, 16:36
you're totally right, thanks for your information. the protection scheme turned out to be nothing fancy, which is a shame because the application itself is pretty advanced.

still unanswered is why (my best guess is accidently) the symbol loader goes nuts. would be nice to exploit this.

o well, i did learn about calling conventions in the end