Flag: Tornado! Hurricane!

 Forums >>  Debuggers  >>  LDR_Module (Anti-Debugging) Question

Topic created on: September 10, 2007 14:35 CDT by lafkuku .

Well I'm still kind of new to reversing, been working on this stuff for about 6ish months. I ran into this anti-debugging trick in a crackme. The trick is posted on this site under the reference library. However it doesn�t give much information on why this works. Other than once it detects memory allocated and sees a library referenced it knows a debugger exists.

(link: http://www.openrce.org/reference_library/anti_reversing_view/33/Ring3%20Debugger%20Detection%20via%20LDR_MODULE/)

I've looked all over the net trying to find references to this to understand; with no luck (maybe I�m using the wrong keywords?). Specifically why the memory is allocated in the LDR_Module when a ring 3 debugger is present and why not when one isn�t. I was hoping someone could point in the right direction or explain it a little.

Also, any generic methodology on how a script might be written to bypass this trick would also be helpful (or a link to a resource explaining it). I can do it manually once located in the binary, however, I�m curious what the approach would be if you wanted to automate it.


     John

  jms     September 10, 2007 15:08.27 CDT
Why don't you post the link to the crackme, and some of us can take a look.

  lafkuku     September 10, 2007 15:34.22 CDT
> jms: Why don\'t you post the link to the crackme, and some of us can take a look.

Well the problem isnt in the crackme, I can get around the anti-debugging trick easily by setting flags etc. And the anti debugging trick is implemented exactly how the link in the reference section of this site describes it (under references->anti-reversing->ring 3 dection via LRD_Module)

I�m curious on how/why this particular type of anti-debugging trick works. More specifically why detection is possible due to the LDR_Module structure be initialized and why is it initialized during debugging and not when the target isn�t being debugged.

But for reference here is a snippet of the anti-debugging trick used in the crackme, which is virtually the same as the one I mentioned above except what happens after detection.


004010CD   . 33F6           XOR ESI,ESI                        
004010CF   . 57             PUSH EDI
004010D0   . 8BF9           MOV EDI,ECX
004010D2   . 8975 EC        MOV DWORD PTR SS:[EBP-14],ESI
004010D5   . 8975 F0        MOV DWORD PTR SS:[EBP-10],ESI
004010D8   . 50             PUSH EAX
004010D9   . 64:A1 30000000 MOV EAX,DWORD PTR FS:[30]          ;Grabs the PEB struct
004010DF     8B40 0C        MOV EAX,DWORD PTR DS:[EAX+C]       ;Goes to the PPEB_LDR_Data struct
004010E2     40             INC EAX                            ;linear search though address space 1 byte at a time
          
004010E3     FF45 F0        INC DWORD PTR SS:[EBP-10]
004010E6   . 817D F0 000500>CMP DWORD PTR SS:[EBP-10],500      ;if we checked 500 bytes and no lib found
004010ED     74 0F          JE SHORT Crackme1.004010FE         ;jump to passed code
004010EF   . 8138 EEFEEEFE  CMP DWORD PTR DS:[EAX],FEEEFEEE    ;Checking for an initilized lib
004010F5   .^75 EB          JNZ SHORT Crackme1.004010E2        ;jump to start of loop
004010F7     C745 EC 010000>MOV DWORD PTR SS:[EBP-14],1        ;if found set bool to true
004010FE   > 58             POP EAX
004010FF   . 3975 EC        CMP DWORD PTR SS:[EBP-14],ESI      ;esi = 0
00401102   . 74 21          JE SHORT Crackme1.00401125         ;jump to notBeingDebugged code or drop to fail and screw up the EIP, throwing AV exception


edit* added a comma and fixed a comment

  jms     September 10, 2007 16:03.00 CDT
Well it would be useful to have the binary, as I could script something in ImmunityDebugger that would show how to automagically bypass this. Email me @ jms @ bughunter.ca

  Kayaker     September 10, 2007 19:39.58 CDT
Hi

I believe the trick is based on the difference in heap allocations between release and debug (or under a debugger) versions, and the call to RtlAllocateHeap when the PEB_LDR_DATA structure is created.  A slightly larger heap allocation than requested is made, which includes the 0xFEEEFEEE at the end for whatever reason.

PEB_LDR_DATA is allocated in ntdll!LdrpInitializeProcess as can be seen in the following:


:7C921ABC _LdrpInitializeProcess@20 proc near     ; CODE XREF: _LdrpInitialize(x,x,x)+88CE
...
:7C921B36                 mov     eax, large fs:18h ; TEB
:7C921B3C                 mov     ebx, [eax+30h]  ; PEB
:7C921B3F                 lea     edi, [ebx+8]    ; PEB.ImageBaseAddress
:7C921B42                 push    dword ptr [edi]
:7C921B44                 call    _RtlImageNtHeader@4 ; RtlImageNtHeader(x)
...
:7C921D7F                 xor     esi, esi
...

:7C92202B                 push    28h
:7C92202D                 pop     edi
:7C92202E                 push    edi
:7C92202F                 add     eax, 40000h
:7C922034                 push    eax
:7C922035                 push    _LdrpHeap

:7C92203B                 call    _RtlAllocateHeap@12 ; RtlAllocateHeap(x,x,x)

:7C922040                 cmp     eax, esi
:7C922042                 mov     [ebx+0Ch], eax  ; PEB_LDR_DATA allocated
:7C922045                 jz      loc_7C93E932
:7C92204B
:7C92204B loc_7C92204B:                           ; CODE XREF: LdrpInitializeProcess(x,x,x,x,x)+1CEAEj
:7C92204B                 mov     eax, [ebx+0Ch]
:7C92204E                 mov     [eax+_PEB_LDR_DATA.Length], edi
:7C922050                 mov     eax, [ebx+0Ch]
:7C922053                 mov     [eax+_PEB_LDR_DATA.Initialized], 1
:7C922057                 mov     eax, [ebx+0Ch]
:7C92205A                 mov     [eax+_PEB_LDR_DATA.SsHandle], esi
:7C92205D                 mov     eax, [ebx+0Ch]
:7C922060                 mov     [eax+_PEB_LDR_DATA.EntryInProgress], esi
:7C922063                 mov     eax, [ebx+0Ch]
:7C922066                 add     eax, 0Ch
:7C922069                 mov     [eax+LIST_ENTRY.Blink], eax ; PEB_LDR_DATA.InLoadOrderModuleList
:7C92206C                 mov     [eax+LIST_ENTRY.Flink], eax
:7C92206E                 mov     eax, [ebx+0Ch]
:7C922071                 add     eax, 14h
:7C922074                 mov     [eax+LIST_ENTRY.Blink], eax ; PEB_LDR_DATA.InMemoryOrderModuleList
:7C922077                 mov     [eax+LIST_ENTRY.Flink], eax
:7C922079                 mov     eax, [ebx+0Ch]
:7C92207C                 add     eax, 1Ch
:7C92207F                 mov     [eax+LIST_ENTRY.Blink], eax ; PEB_LDR_DATA.InInitializationOrderModuleList
:7C922082                 mov     [eax+LIST_ENTRY.Flink], eax
:7C922084                 push    dword ptr [ebx+8]
:7C922087                 call    _LdrpAllocateDataTableEntry@4 ; LdrpAllocateDataTableEntry(x)
...


If you trace into the PEB_LDR_DATA RtlAllocateHeap when a process is starting under a debugger you will see it call RtlDebugAllocateHeap.  The 0xFEEEFEEE that the antidebug technique detects can be easily seen using Softice for example. Start notepad, Ctrl-D into Softice, change the address context to notepad and put a breakpoint on 7C92203B   call    _RtlAllocateHeap.  Then start another instance of notepad under OllyDbg and it should break. Step over the mem allocation call and you can see the effect.

Kayaker

  lafkuku     September 10, 2007 19:55.17 CDT
Thanks kayaker,
   Thats what i kinda figure out after a few more hours of research into the area. I've written a small ID script which scans through and removes the FEEEFEEE added into the allocation. Could be better though, it's just something i put together to test this.

From what i gather the FEEEFEEE is added in order to allow the debugger keep track of the heap for the purpose of freeing (Could be completely wrong here). So I dont know if this method inadvertently adds a memory leak. But here is what i came up with, which seems to work with no errors.

If anyone else has any more insight into exactly what's up with the FEEEFEEE string let me know i'd be very thankful.


def ldrModDefeat(imm):
  searchLong = 0xeefeeefe
  ldrModPtr = imm.getPEBaddress() + 0x0c
  ldrMod = imm.readLong(ldrModPtr)
  i = 0
  while i < 5000:
    d = str2int32(imm.readMemory(ldrMod + i, 8))
    i += 1
    if d == searchLong:
      imm.writeLong(ldrMod + i, 0x00000000)


  ero     September 18, 2007 05:14.59 CDT
After some googling...

Wikipedia article: "0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory"

Memory Debug Codes:
"Windows NT memory codes
0xABABABAB - Memory following a block allocated by LocalAlloc().
0xBAADF00D - "Bad Food". This is memory allocated via LocalAlloc( LMEM_FIXED, ... ). It is memory that has been allocated but not yet written to.
0xFEEEFEEE - OS fill heap memory, which was marked for usage, but wasn't allocated by HeapAlloc() or LocalAlloc(). Or that memory just has been freed by HeapFree()."


Win32 Debug CRT Heap Internals:
"HeapFree() will be called to return the block to the win32 heap. This causes the block to be overwritten with the win32 heap's "freed memory" pattern, which is 0xFEEEFEEE"

So it seems the case is that if the debugger is running, a special implementation of the heap allocation functions will be called, and that's what the trick checks for.

  ero     September 18, 2007 07:03.51 CDT
Another anti-debug test is to check NtGlobalFlags in the PEB  to see if it equals 70h (FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS)

I have the feeling that FLG_HEAP_ENABLE_FREE_CHECK is strongly related to the usage of 0xFEEEFEEE. Haven't tested it myself tho.

In this nice article a couple of ways of overcoming the check are given.

Note: Registration is required to post to the forums.

There are 31,314 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
hi!
Jul/01
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit