PDA

View Full Version : Simple Reverse Engineering


chmckay
14th June 2004, 07:35 PM
I'm currently doing a little reverse engineering of Coredll so that I can understand how a few functions work. Occasionally I run across a function call to an address similar to F000BDD8. Is this a function call into the kernel or does it correspond to an address in the dll? If someone could point me to the correct reference, I'd appreciate it.

This is how it is layed out:

LDR r0, &0000b650
MOV lr, pc
MOV pc, r0

And at address 0000b650 the value is F000BDD8.

Thanks!

mamaich
15th June 2004, 01:50 AM
it is something like a "syscall" command on WinCE. The "FIRST_METHOD" value (0xF0010000) is subtracted form the given address, then value is divided by 2 (in your case we get -8468 or 0xff..ffdeec). If the value is negative it is "API call to an implicit handle. In this case, bits 30-16 of the method index indicate which entry in the system handle table." (probably its a typo in comment, bits 8-22 are used instead of 30-16). Lower bits are offset in SystemAPISets[] table for the function address.
For more information look into PrefetchAbort function in "PRIVATE\WINCEOS\COREOS\NK\KERNEL\ARM\armtrap.s" file, and ObjectCall function in "PRIVATE\WINCEOS\COREOS\NK\KERNEL\objdisp.c"

You should get PlatformBuilder and look into Wince 4.20 partial source code that is coming with it. It does not have much information on indexes inside SystemAPISets table for any table except for SystemAPISets[SH_WIN32] (SH_WIN32 == 0).

itsme
15th June 2004, 09:55 AM
see this (http://www.xs4all.nl/~itsme/projects/xda/wince-systemcalls.html) page for a list of systemcalls.

and this (http://www.xs4all.nl/~itsme/projects/xda/wince-kernelinfo.html) page for a description of how systemcalls work.

to convert a trap address ( like 0xF000BDD8 ) back to the syscall nrs:

$a= (0xf0010000-$addr)/4; # = 0x108a
$api=$a>>8; # 0x10 = SH_GDI
$call=$a&0xff; # 0x8a = ExtCreateRegion

( call defined in public/common/oak/inc/mwingdi.h )

hmm. not sure which is correct though, my wince-systemcalls page lists a different call signature than the headerfile. they should match.

chmckay
15th June 2004, 05:01 PM
Thank you for the information. I actually have the sample source that comes with the Platform Builder demo. In this case, the call I was investigating was the GetSysColorBrush API.

That brings me to another point. In several of the APIs a check is made to a value (KData->lpvTls[-20], I believe) to see if the 0-bit is 1. The only thing I can determine is whether or not this is checking for the ready state of the API. Whatever the case, it seems that this bit determines whether the function I mentioned earlier is called or whether a function address is loaded from RAM. It's really weird.

The main reason I'm doing this is so that I can access the system's brush cache for the system colors. I've noticed that if I intercept calls to GetSysColor and GetSysColorBrush, it only works for applications that have not called them yet. So, if I override the color for COLOR_BTNFACE, menubars for newly launched applications are colored correctly, but buttons (which belong to GWES) do not use the appropriate color. It's weird because my code has been injected into GWES.Exe.

I guess that brings me to my ultimate question of whether or not someone can point me to the location in RAM where the system brush cache is stored.

Thanks!

itsme
16th June 2004, 12:09 AM
is the '-20' in bytes ?


in PUBLIC/COMMON/OAK/INC/pkfuncs.h
#define PRETLS_THRDINFO -5

#define UTLS_INKMODE 0x00000001 // bit 1 set if in kmode
#define IsThrdInKMode() (UTlsPtr()[PRETLS_THRDINFO] & UTLS_INKMODE)

this must be the bit that is set when calling 'SetKmode();'

chmckay
16th June 2004, 12:44 AM
Yeah, the -20 is in bytes. Here's the disassembly of what I was looking at:

00B5EC E59F6068 LDR r6, &0000B65C
00B5F0 E59F5060 LDR r5, &0000B658
00B5F4 E5960000 LDR r0, [r6, #0]
00B5F8 E5101014 LDR r1, [r0, #-20]
00B5FC E3110001 TST r1, #1
00B600 15950000 LDRNE r0, [r5, #0]
...
00B650 F000BF08 ANDNV r11, r0, r8, LSL #30
00B654 01FC6758 MVNEQS r6, r8, ASR r7
00B658 01FC6760 MVNEQS r6, r0, ROR #14
00B65C FFFFC800 SWINV &FFC800 <-- Points to KDataStruct

What you said makes sense, yet it seems kind of strange that this API would be looking at an offest of -20.

itsme
16th June 2004, 01:21 AM
so what you are seeing, is a call to 'IsThrdInKMode()' .
there is a space of thread local storage used by the kernel, just before the publicly accessible thread local storage. - look for SIZE_PRETLS, and PRETLS_RESERVED in the wince source.

this function ( well implemented as a macro actually ) is not a very strange function to call from a system call.

btw, you should have a look at IDA from datarescue. it will give you a much more readable disassembly. the stuff in your example from 00b650-b65c will be recognised as a constant pool, and the references to it, like at 00b5ec will be disassembled as 'LDR r6, =0xffffc800'

chmckay
16th June 2004, 01:28 AM
The only problem I have with IDA is that I can't afford it and their demo doesn't handle ARM processors. The generated output was done with a fairly simple program and has forced me to learn quite a bit about the underlying code in the OS. I've had to go back and forth between the disassembly and the shared source, but I've managed so far (with this exception).

I do have one other question while I have your attention. I've managed to inject a dll into all of the running processes and I've successfully managed to intercept several APIs by patching an application's IAT (and all attached modules, too) in an attempt to provide a better color handler for the system. It appears, however, that some programs, like Gwes.exe, don't use call my functions, but instead call the functions built into Coredll. For example, the GetSysColorBrush I mentioned earlier. This is what prompted me to begin reverse engineering Coredll in the first place. Do you know if the addresses are being stored somewhere? If so, that would explain why even though I've patched the IAT that the original function is still being called.

mamaich
16th June 2004, 04:29 AM
contact me in PM, I can help with IDA 4.51 full

itsme
16th June 2004, 09:08 AM
gwes.exe is the program implementing the API, so quite likely it either calls it's api's directly, or calls the systemcalls directly.

and maybe someprograms are linked to a statically linked version of coredll?

a while back I experimented with trapping systemcalls, by modifying the method table in an API. ( see hookapi.cpp (http://viewcvs.xda-developers.com/cgi-bin/viewcvs.cgi/xdautils/loaderhook/hookapi.cpp?rev=HEAD&content-type=text/vnd.viewcvs-markup) )
I do remember that my device became very unstable. so I guess that it somewhat worked, but haven't figured out what exactly I did wrong yet.

btw, I would be quite interested to see your code to trap calls via the IAT.

JohnSmith
16th June 2004, 05:39 PM
When you have a look to romimage.exe source code in platform builder you will notice that there is a special handling for coredll.dll.

All programs included in the MODULES section will directly resolve calls to coredll.dll. Only if you build a new XIP section a warning will appear "missing coredll.dll ... will late bind".

This means that a hook to coredll.dll will not be visible for in ROM programs since they will call the system functions directly (without the trap).

John

chmckay
17th June 2004, 12:13 AM
btw, I would be quite interested to see your code to trap calls via the IAT.
Unfortunately, I'm not at the computer where I have the code, so I'll have to upload it to you tomorrow. However, it involves extracting the IAT from the PPROCESS structure of a given program, then enumerating through the entries until I find the API I'm looking for. It's actually pretty straight forward. Give me your email address and I'll send it to you as soon as I can.

When you have a look to romimage.exe source code in platform builder you will notice that there is a special handling for coredll.dll.

All programs included in the MODULES section will directly resolve calls to coredll.dll. Only if you build a new XIP section a warning will appear "missing coredll.dll ... will late bind".

This means that a hook to coredll.dll will not be visible for in ROM programs since they will call the system functions directly (without the trap).
I don't have the full source code, only what's available in the shared source, so I'm not sure what modules would be affected. However, I'm really only interested in a few of the Gwes APIs. I know it's possible at least at some point to hook into those as I've seen it done, though the individual who did it is under an NDA and can't tell me how he did it.

Itsme's process looks to be about the best so far, assuming I can get it to work. The only thing is that I need to find a way to translate the physical address to a virtual adress (and vice-versa) for MIPS, SH3 and the emulator, not just the ARM/XScale processors. If I could do that, then I might be able to get things to work.

Thanks for all of your help so far. I appreciate the time you have spent in explaining a few things to me.

itsme
17th June 2004, 02:00 AM
itsme@xs4all.nl

for translating physical to virtual you would need to find the translation tables for each process, which I assume must exist somewhere, but have not found them yet. - my guess is it may be the 'pPTBL' entry from the process struct, but have not verified this yet.


( you know that virtual addresses can not uniquely be translated back to physical without knowing what process they are for? for instance the virtual address 0x11000 is visable in each process, and mapped to a different physical address each time. )

chmckay
17th June 2004, 04:03 AM
Fortunately, I've written an OS before, so I know what you mean about address mapping. If the pTBL does contain the page mappings, that would make sense. I found it easier in my OS to keep the TLB entries with the process they belonged to. That way the OS wouldn't have to search through its memory chain looking for the process's mappings.

Also, if the pTBL does contain the TLB entries, then it should be relatively easy to decode the addresses. After reading your code, itsme, I determined that the CINFO structure holds a pServer field which points to the process which contains the APIs. So, for example, the GDI and USER API sets are being held in Gwes.exe (at least, according to the pServer field). The ppfnMethods field is a VA referring to the pServer. If pServer is NULL, then the ppfnMethods field seems to be a PA. So, what I could do is check for pServer. If it is NULL, I could use the current process's pTBL structure to map the PA to a VA. If the pServer field is non-NULL, then I could try the pServer's pTBL field to do the mapping and then do the replacement that way.

If this works, I owe you big!

itsme
17th June 2004, 11:28 AM
here (http://viewcvs.xda-developers.com/cgi-bin/viewcvs.cgi/xdautils/leds/testpi.cpp?rev=1.2&content-type=text/vnd.viewcvs-markup) is another experimental program, that investigates all the handles present in the system.

I used it to generate this (http://www.xs4all.nl/~itsme/projects/xda/wince-handles.txt) overview of handles.

chmckay
18th June 2004, 04:38 AM
I just thought I'd post an update on my progress so far. It appears that I can overwrite the API table pretty easily. Instead of taking a physical address, the table takes a pointer to a function in virtual memory. You just need to map it to slot 0 using MapPtrToProcess.

I've come across two issues in doing this. The first thing is that I can't call the original function address. For example, I store the original address contained in ppfMethods[x] and then attempt to typecast it to the proper function type, passing the incoming variables.

The other issue is that it appears that the API table is NOT refreshed upon a soft-reset. Fortunately, I was playing around with it on the emulator. Had I not, I would have been forced to hard-reset my device.

Does anyone have ideas on either of these issues?

Thanks again for your help so far!

itsme
18th June 2004, 03:06 PM
a thing that just occurred to me, is that if you duplicate the apiset struct, the memory pointed to by ppfnMethods should be readable from the process specified in pServer.

so you should allocate the memory in the address space of pServer.
or set pServer to yourself, and add some hook code which does not modify the stack, so you can just pass most calls directly to the original server.

to call the original function address, you have to somehow switch process context, and then call it.

chmckay
18th June 2004, 11:24 PM
Well, in the case that I tested, I replaced the QueryAPISetID API which exists in Wn32 and therefore has no pServer. It appears that if there is no pServer, then there is no context switch needed. I've been able to verify that the API will execute my code and the generated assembly does not modify the stack in any way.

This one is really weird. Thanks for the suggestions.

michar
30th June 2005, 04:31 PM
btw, I would be quite interested to see your code to trap calls via the IAT.
Unfortunately, I'm not at the computer where I have the code, so I'll have to upload it to you tomorrow. However, it involves extracting the IAT from the PPROCESS structure of a given program, then enumerating through the entries until I find the API I'm looking for. It's actually pretty straight forward. Give me your email address and I'll send it to you as soon as I can.


Hi,

Just wondring if you could post/PM/email me the code that lets you replace the API call. This is for the purpose of hooking a different DLL to do my own thing, or see here:
http://forum.xda-developers.com/viewtopic.php?p=131857#131857

chmckay
5th July 2005, 07:38 AM
I just sent you a PM with the information you requested.

deus
13th July 2005, 11:25 AM
I just sent you a PM with the information you requested.

Hi,

Can you pleaese please send me via PM or mail the source code which proivde replaceing an API function call.
I'm trying for several days hooking specified DLL...

It can help me a lot.

Thanks,

Eric.