Valhalla Legends Forums Archive | General Programming | How to get around GetProcessHeap in dllmain

AuthorMessageTime
warz
I've encountered a problem while implementing my own call to checkrevision. There's a loop within the function, infact, the loop looks like so (with some of my commenting)....

[code]
.text:0040165B CheckFilesLoop:                        ; CODE XREF: CheckRevision+F1j
.text:0040165B                mov    eax, [esi]      ; Loop 1 - EAX becomes base addr of lockdown
.text:0040165B                                        ; Loop 2 - EAX becomes base addr of starcraft.exe
.text:0040165B                                        ; Loop 3 - EAX becomes base addr of storm.dll
.text:0040165B                                        ; Loop 4 - EAX becomes base addr of battle.snp
.text:0040165B                                        ; Loop 5 - EAX becomes base addr of pplug114 (0 for now)
.text:0040165B                                        ;
.text:0040165D                cmp    eax, ebx        ; EBX = 0
.text:0040165F                jz      short loc_401670 ; Jump if no base addr (loop 5 we jump)
.text:0040165F                                        ;
.text:00401661                push    eax            ; Loop 1 - Push lockdown base addr
.text:00401661                                        ; Loop 2 - Push sc.exe base addr
.text:00401661                                        ; Loop 3 - Push storm base addr
.text:00401661                                        ; Loop 4 - Push battle base addr
.text:00401662                lea    eax, [ebp+var_108]
.text:00401668                push    eax            ; Loop 1 - Push ptr to value (00000200)
.text:00401668                                        ; Loop 2 - Push ptr to modified value (00332200)
.text:00401668                                        ; Loop 3 - Push ptr to modified value (01782200)
.text:00401668                                        ; Loop 4 - Push ptr to modified value (01AC2200)
.text:00401668                                        ;
.text:00401669                call    BeginExeCheck  ; The value 200h pointed to by arg1 is replaced
.text:00401669                                        ; by 32200h after call. EAX holds 1 on success.
.text:00401669                                        ; EDX holds 150608h, which points to 00 C5 97 7C.
.text:00401669                                        ; Produces a SHA1 digest at arg2+8, and extends
.text:00401669                                        ; recursively past.
.text:0040166E                pop    ecx
.text:0040166F                pop    ecx            ; Loop 1 - ECX holds lockdown base addr again
.text:0040166F                                        ; Loop 2 - ECX holds sc.exe base addr again
.text:0040166F                                        ; Loop 3 - ECX holds storm base addr again
.text:0040166F                                        ; Loop 4 - ECX holds battle base addr again
.text:00401670
.text:00401670 loc_401670:                            ; CODE XREF: CheckRevision+CEj
.text:00401670                add    edi, 4          ; Loop 1 - EDI is 0, and ends up being 4
.text:00401670                                        ; Loop 2 - EDI is 4, and ends up being 8
.text:00401670                                        ; Loop 3 - EDI is 8, and ends up being C
.text:00401670                                        ; Loop 4 - EDI is C, and ends up being 10
.text:00401670                                        ; Loop 5 - EDI is 10, and ends up being 14
.text:00401670                                        ;
.text:00401673                mov    eax, edi        ; Loop 1 - EAX = 4
.text:00401673                                        ; Loop 2 - EAX = 8
.text:00401673                                        ; Loop 3 - EAX = C
.text:00401673                                        ; Loop 4 - EAX = 10
.text:00401673                                        ; Loop 5 - EAX = 14
.text:00401673                                        ;
.text:00401675                sar    eax, 2          ; Loop 1 - EAX becomes 1
.text:00401675                                        ; Loop 2 - EAX becomes 2
.text:00401675                                        ; Loop 3 - EAX becomes 3
.text:00401675                                        ; Loop 4 - EAX becomes 4
.text:00401675                                        ; Loop 5 - EAX becomes 5
.text:00401675                                        ;
.text:00401678                add    esi, 4          ; Loop 1 - ESI becomes 038C4004
.text:00401678                                        ; Loop 2 - ESI becomes 038C4008
.text:00401678                                        ; Loop 3 - ESI becomes 038C400C
.text:00401678                                        ; Loop 4 - ESI becomes 038C4010
.text:00401678                                        ; Loop 5 - ESI becomes 038C4014
.text:00401678                                        ;
.text:0040167B                cmp    ds:off_4030B8[eax*4], ebx ; Loop 1 - Check for sc.exe base addr
.text:0040167B                                        ; Loop 2 - Check for storm base addr
.text:0040167B                                        ; Loop 3 - Check for battle base addr
.text:0040167B                                        ; Loop 4 - Check for pplug114 base addr
.text:0040167B                                        ; Loop 5 - No more files to check
.text:0040167B                                        ;
.text:00401682                jnz    short CheckFilesLoop ; Loop 1 - Jump is taken
.text:00401682                                        ; Loop 2 - Jump is taken
.text:00401682                                        ; Loop 3 - Jump is taken
.text:00401682                                        ; Loop 4 - Jump is taken
.text:00401682                                        ; Loop 5 - Jump is not taken.. done!
.text:00401684
[/code]

... this loop grabs pointers to the base addresses of the main game files from a global variable. The problem is, I think, is that checkrevision's dllmain function now calls GetProcessHeap, and stores it in a global hHeap variable. This is the variable that is read from when "; Loop 2 - EAX becomes base addr of starcraft.exe".

When my test application calls checkrevision, the ptr returned points to the same base address, but is not a ptr to sc.exe (like it should be). So, when this loops reads from the hHeap variable, it grabs a different value than it requires for success. Somewhere within the BeginExeCheck function I have there, there is a 20-byte (looks like SHA1, but havent found any calls to SHA1Update, so it must be loading the address of SHA1Update into a register and then calling it) result being produced. The only values passed to the function are the ptr to the game files base addr, and a ptr to a dword value being generated as this loop progresses. So I have reason to believe the resulting 20-byte value, as well as the dword value, are based on the address passed to the BeginExeCheck function. I should also note, that these values stay the same - provided the same 'value string' and same dll #.

My question is - is there any way to fool this loop into grabbing the base address of the loaded starcraft.exe, instead of my main application? One thing I had in mind was to manually edit that value in memory prior to calling checkrevision, and hook HeapAlloc, etc, to allocate proper space (they read from the hHeap variable created by dllmain), but this seems a little too much. It's also not very safe. Who knows where this variable is referenced.

I can't hook in the middle of this loop because there's no exported ordinal, and the addresses change from dll to dll. So, how to get this loop to read from sc.exe, instead of my calling test app?
November 14, 2006, 1:34 AM
warz
Looks like I was looking at the wrong data ptr. It's reading from ESI. ESI holds a ptr to the beginning of the data segment. The first few values in the data segment are our necessary pointers.
November 14, 2006, 3:25 AM

Search