Jump to content
Tuts 4 You
Sign in to follow this  
Pancake

Manual dll map - weird problem

Recommended Posts

Pancake

Hello. I got my old code with this feature which i wanted to review, and something very strange happens. All the relocations/imports etc are properly resolved but the program crashes when invoking the DllMain. If i run it in olly, everything works fine (and i see MessageBox from process attach). The loader run as administrator hangs inside DllMain not displayin anything, and run without elevated privileges just crashes.

When i removed plugins from olly it also hangs like in first case. What may be the cause??

Edit: After checking the dll, the function which causes freeze (when manually mapped) is "dllmain_crt_dispatch"

Edit: I am doin some mistake with allocation. After stepping throught entire crt init i noticed, that it hangs inside loop "LOCK CMPXCHG DWORD PTR DS:[ESI],ECX". Normally there are 00 00 00 00 here. In my case, i found "0D F0 AD BA" blocks (which mean something in msvc with allocation). So thats a step forward... :)

Edit: Yeah that was that. Zeroing memory after allocation did the trick. Resolved issue talkin to myself here on forum :) Maybe someone will find it useful someday.

Edited by Pancake (see edit history)

Share this post


Link to post
Pancake

Hey its me again :)
I got problem with static stuff, for example singleton's constructor is not called in manually mapped file! Im havin trouble fixin this, something with TLS section but i got no idea what should i do with that :(

Share this post


Link to post
Pancake

Im still confused. I read that i have to call the DllMain with DLL_THREAD_ATTACH for every callback before DLL_PROCESS_ATTACH which runs the dll? So how do i pass the callback address to Dllmain? Or do i have to call each tls callback with (hinstance, DLL_THREAD_ATTACH, reserved) arguments? Still, what for are indexes in tls table, and the raw data is not referenced anywhere. The "AddressOfCallBacks" start with 3 zero dwords and then with 3 function addresses, why the zeroes? There is so much i dont understand here :(

Edited by Pancake (see edit history)

Share this post


Link to post
atom0s

TLS callbacks should be called with DLL_PROCESS_ATTACH on their first initial call. (Also keep in mind the process/module can have more than one TLS callback.)

Share this post


Link to post
Pancake

But "how" should they be called?

Thats my TLS table after fixing relocations and imports. Mapped base 7EF80000

->TLS Table
   StartAddressOfRawData:  0x1F000 -> 00 00 00 00 00 00 00 80
   EndAddressOfRawData:    0x1F008
   AddressOfIndex:         0x1DA94 -> only zero
   AddressOfCallBacks:     0x15168 -> 00 00 00 00 00 00 00 00 7C AD F8 7E CC 15 F9 7E 69 5C F8 7E 00 00 00 00
   SizeOfZeroFill:         0x00000000
   Characteristics:        0x00300000

So i see two 0 dwords in the callback table (why zero and not addresses?), then 3 addresses from codesection. I tried calling them with dllbase and dll_thread_attach/dll_process_attach but it crashes.

Thats piece of code where the constructor is skipped.

MOV EAX,DWORD PTR FS:[0x2C] // this is wrong when mapped manually
MOV ECX,DWORD PTR DS:[_tls_index]
MOV ECX,DWORD PTR DS:[EAX+ECX*4]
MOV EAX,DWORD PTR DS:[0x638933B0]
CMP EAX,DWORD PTR DS:[ECX+4] // this cmp behaves differently

Edited by Pancake (see edit history)

Share this post


Link to post
atom0s

Tls callbacks are called just like DllMain of a DLL. They take 3 params but have no return. In C++ they look like this:

void __stdcall TlsCallback(PVOID lpModuleHandle, DWORD fdwReason, PVOID lpContext) { }

The first param is the current applications base address, second param is the reason the Tls was called (ie. DLL_PROCESS_ATTACH), and the third is the context / reserved param that is generally not used and can just be null/0. 

You can see how UPX invokes Tls callbacks here:

https://github.com/korczis/upx/blob/be081ef98d4c5b967d203ea0261286d8d2e77449/src/stub/src/i386-win32.pe.S#L226

Share this post


Link to post
Pancake

Okay i figured out these are NOT tls callbacks causing problems. Its the raw data. I need to call LdrpHandleTlsData routine and it makes the fs:[2c] work and maps the raw data from tls section so everything works fine. But sadly this is not exported by ntdll which makes it not portable, right now im using hardcoded ntdll offset for my OS version

The second possibility is to do it manually, allocate memory, copy the static TLS buffer and set in in the PEB like in code below:

https://github.com/DarthTon/Blackbone/blob/master/src/BlackBoneDrv/MMap.c#L1280

 

Edited by Pancake (see edit history)

Share this post


Link to post
mudlord

Is this for something like a exe packer? not sure im following what you are trying to do exactly. trying to load a DLL completely from memory?

Edited by mudlord (see edit history)

Share this post


Link to post
A200K
On 4.5.2016 at 11:07 AM, mudlord said:

Is this for something like a exe packer? not sure im following what you are trying to do exactly. trying to load a DLL completely from memory?

Yes, manual mapping is like calling the windows api func LoadLibrary, but doing all necessary stuff the windows loader would do by yourself, and you don't need to have the dll located on your hard drive.

Could be used for a packer, to insert/pack other dlls into an executable file, so you have only one exe file left but you still have the functionality of the dlls.

Could be used for other application modification as well, e.g. for game hacking :)

Edited by A200K
Corrected typo lol (see edit history)

Share this post


Link to post
Pancake

Yes just load dll from memory. I never had to use tls because all of my stuff was written in c++ which did not use tls. But in new visual studio the compiler started using fs:[2c] for static things. And so i have to manually call nonexported LdrpHandleTlsData (or something like that, forgot name) but this function is not exported by ntdll and so offset varies on every OS. I dont know how to fix that

Share this post


Link to post
atom0s
1 hour ago, Pancake said:

Yes just load dll from memory. I never had to use tls because all of my stuff was written in c++ which did not use tls. But in new visual studio the compiler started using fs:[2c] for static things. And so i have to manually call nonexported LdrpHandleTlsData (or something like that, forgot name) but this function is not exported by ntdll and so offset varies on every OS. I dont know how to fix that

11

There are a few manual mapping examples around the net that have implementations of this you could look into. This is one of the more up to date ones of a manual map implementation that is public:

https://github.com/DarthTon/DarkMMap

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×
×
  • Create New...