Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   beating IsDebuggerPresent for my unpacker (https://forum.exetools.com/showthread.php?t=6979)

0x539 02-28-2005 01:13

beating IsDebuggerPresent for my unpacker
 
hi, could anybody explain me how to defeat IsDebuggerPresent?
i downloaded some sources of olly plugins but i dont understand
what they are actually doing. source code would be nice.

D-Jester 02-28-2005 09:10

Looking for this...?
 
Code Taken From: Guide on How to play with processes memory, write loaders and Oraculums

http://www.exetools.com/forum/showthread.php?t=6556

Many Thanks to Shub-Nigurrath

Code:

unsigned long KillisDebuggerPresent()
{
        FARPROC addrIDP; //Buffer for API Address IsDebuggerPresent
       
        BYTE rdt[13]; //Buffer to read to (Total of 13 bytes)
            BYTE wrt[3] = {0x33, 0xC0, 0xC3}; /*(Bytes to write (patch):
                                                33C0        xor eax, eax
                                                C3        ret
                                          */
        unsigned long byteswritten=0;
       
        DWORD oldpr=0;
       
        HINSTANCE hKer;
        HANDLE hProcess = GetCurrentProcess();
       
        hKer = GetModuleHandle("KERNEL32");
        ZeroMemory(rdt,16);
       
        addrIDP = GetProcAddress(hKer, "IsDebuggerPresent");
       
        VirtualProtectEx(hProcess, (LPVOID)addrIDP, 3, PAGE_READONLY, &oldpr);
        ReadProcessMemory(hProcess, (LPVOID)addrIDP, (LPVOID)rdt, 13, NULL);
        VirtualProtectEx(hProcess, (LPVOID)addrIDP, 3, oldpr, &oldpr);
       
        // Check api signature
        if (rdt[0]==0x64 && rdt[1]==0xA1 && rdt[2]==0x18  && rdt[3]==0 && rdt[4]==0 && rdt[5]==0 && rdt[6]==0x8B && rdt[7]==0x40 && rdt[8]==0x30 && rdt[9]==0x0F && rdt[10]==0xB6 && rdt[11]==0x40 && rdt[12]==0x02)
        {       
                __asm
                {
                        add addrIDP, 9
                }
               
                VirtualProtectEx(hProcess, (LPVOID)addrIDP, 3, PAGE_READWRITE, &oldpr);
                WriteProcessMemory(hProcess, (LPVOID)addrIDP, (LPVOID)wrt, 3, &byteswritten);
                VirtualProtectEx(hProcess, (LPVOID)addrIDP, 3, oldpr, &oldpr);
        }
        return byteswritten;
}

Regards...

TQN 02-28-2005 13:36

I was not read the tutor of Shub-Nigurrath yet, but with the above code, I have a wonder: this function will be called from: the loader or the victim process.

dyn!o 02-28-2005 20:00

IsDebuggerPresent is the most weak anti-debug check.

If you want to defeat it then I would propose the following:

- modification of kernel32.dll (overwriting during the runtime)
- hooking the API itself (if the protection is more sophisticated and computes the checksum of it then usually it checks only first few instructions, you should be still able to set the hook at one of the last instructions inside this API)
- modification of IsDebuggerPresent return value in the code space of protected software (e.g. set a hardware breakpoint near the call offset)

Regards.

D-Jester 02-28-2005 21:59

Quote:

Originally Posted by TQN
I have a wonder: this function will be called from: the loader or the victim process.

The code example is the called from the victim. He asked how to defeat it, I'm not going to code it for him.

However with little to no modification this code or its equivalent could be used in combination with y0da's Force Library and thus IsDebuggerPresnt could be defeated via RemoteExec which enables you to execute code within the context of another process

Regards...

Shub-Nigurrath 03-01-2005 02:28

absolutely correct, there are plenty ways to inject code into another one, directly in memory..

see the well known paper, just to start on this argument..

http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c5767

upb 03-01-2005 06:35

another way, doesnt hook anything....
 
Code:

bool DisableBeingDebuggedFlag(HANDLE thread)
{
        CONTEXT ctx;

        ctx.ContextFlags = CONTEXT_SEGMENTS;
        if (!GetThreadContext(thread, &ctx))
        {
                error(FF "GetThreadContext(0x%08X)", FL, thread);
                return false;
        }

        LDT_ENTRY sel;
        if (!GetThreadSelectorEntry(thread, ctx.SegFs, &sel))
        {
                error(FF "GetThreadSelectorEntry(0x%08X)", FL, thread);
                return false;
        }

        DWORD fsbase = (sel.HighWord.Bytes.BaseHi << 8| sel.HighWord.Bytes.BaseMid) << 16 | sel.BaseLow;
        DWORD RVApeb;
        SIZE_T numread;

        if (!ReadProcessMemory(hproc, (LPCVOID)(fsbase + 0x30), &RVApeb, 4, &numread) || numread != 4)
        {
                error(FF "ReadProcessMemory(0x%08X, 0x%08X, 0x%08X, ...)", FL,
                        hproc, (fsbase + 0x30), &RVApeb);
                return false;
        }

        WORD beingDebugged;
        if (!ReadProcessMemory(hproc, (LPCVOID)(RVApeb + 2), &beingDebugged, 2, &numread) || numread != 2)
        {
                error(FF "ReadProcessMemory(0x%08X, 0x%08X, 0x%08X, ...)", FL,
                        hproc, RVApeb, &beingDebugged);
                return false;
        }

        beingDebugged = 0;

        if (!WriteProcessMemory(hproc, (LPVOID)(RVApeb + 2), &beingDebugged, 2, &numread) || numread != 2)
        {
                error(FF "ReadProcessMemory(0x%08X, 0x%08X, 0x%08X, ...)", FL,
                        hproc, RVApeb, &beingDebugged);
                return false;
        }

        return true;
}


btw.... Shub-Nigurrath, is this needed for speed optimization or what ?:PPP
Quote:

__asm
{
add addrIDP, 9
}

dyn!o 03-01-2005 07:39

Looks nice (logic). Anyway, won't work on 9x family.

Now, all hardcore maniacs, tell me why? :)

Regards.

upb 03-01-2005 09:02

give me a kernel32.dll from 9x and i'll answer you hehe ;)
(i dont have any laying around here and dont have any docs about win9x TIB, PEB(?!?) either).

dyn!o 03-01-2005 16:53

Hey, that would be too easy ;)

You are accessing segment register to obtain the address of PEB and read process data. Since TEB (or TIB if you like) and PEB are well settled on WinNT clones but not on Win9x family, you have to be familiar with Win9x/WinNT kernels.

TEB is not a problem here because its field is the same on all Windows. The problematic topic in your example is PEB.

By using two additional APIs you will be able to add Win9x compatibility to the method you presented.

I made my homework. Who's next (to tell us which APIs I'm talking about or/and present another solution)?

Regards.

JuneMouse 03-01-2005 17:29

upb you want 9x IsDebuggerPresent raw code in kernel32.dll ??

her it is if you wanted that

Code:

BFF946F6 IsDebuggerPresent    A1 E49CFCBF      MOV EAX,DWORD PTR DS:[BFFC9CE4]
BFF946FB                      8B08            MOV ECX,DWORD PTR DS:[EAX]
BFF946FD                      8379 54 01      CMP DWORD PTR DS:[ECX+54],1
BFF94701                      1BC0            SBB EAX,EAX
BFF94703                      40              INC EAX
BFF94704                      C3              RETN

well on being single stepped through

Code:

DS:[BFFC9CE4]=C00309C8
EAX=00401000 (OLLYDBG.<ModuleEntryPoint>)

second instruction

Code:

DS:[C00309C8]=81752074
ECX=81752094

Code:

817520B4  3C 21 75 81 B0 A0 5F C1 80 0B 75 81 80 26 75 81  <!u° _Á€ u€&u
817520C4  BC 47 74 81 0C D0 5B 83 00 00 00 00 00 00 00 00  ¼Gt.Ð[ƒ........


flag position on compare
Code:

EAX C00309C8
ECX 81752074
EDX 817520D4
EBX 00680000
ESP 0078FE38
EBP 0078FF78
ESI 81752074
EDI 00000000
EIP BFF946FD KERNEL32.BFF946FD
C 0  ES 016F 32bit 0(97A0)
P 1  CS 0167 32bit 0(FFFFFFFF)
A 0  SS 016F 32bit 0(97A0)
Z 0  DS 016F 32bit 0(97A0)
S 1  FS 3517 16bit 81752270(37)
T 0  GS 0000 NULL
D 0
O 1  LastErr ERROR_INVALID_NAME (0000007B)
EFL 00200A86 (O,NB,NE,A,S,PE,GE,G)

flag position after compare
Code:

EAX C00309C8
ECX 81752074
EDX 817520D4
EBX 00680000
ESP 0078FE38
EBP 0078FF78
ESI 81752074
EDI 00000000
EIP BFF94701 KERNEL32.BFF94701
C 0  ES 016F 32bit 0(97A0)
P 0  CS 0167 32bit 0(FFFFFFFF)
A 0  SS 016F 32bit 0(97A0)
Z 0  DS 016F 32bit 0(97A0)
S 1  FS 3517 16bit 81752270(37)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_INVALID_NAME (0000007B)
EFL 00200282 (NO,NB,NE,A,S,PO,L,LE)


on return

Return to 00401005 (OLLYDBG.00401005)

Code:

registers and flag on return
EAX 00000001
ECX 81752074
EDX 817520D4
EBX 00680000
ESP 0078FE38
EBP 0078FF78
ESI 81752074
EDI 00000000
EIP BFF94704 KERNEL32.BFF94704
C 0  ES 016F 32bit 0(97A0)
P 0  CS 0167 32bit 0(FFFFFFFF)
A 0  SS 016F 32bit 0(97A0)
Z 0  DS 016F 32bit 0(97A0)
S 0  FS 3517 16bit 81752270(37)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_INVALID_NAME (0000007B)
EFL 00200202 (NO,NB,NE,A,NS,PO,GE,G)


now ollydbg cant see the address 0xc00309c8

upb 03-01-2005 21:51

well damn...
 
i started reading the MSJ may 1996 article and found another thing that can be used to check for a debugger in win9x:
Quote:

Windows 95 TIB fields
The 20h DWORD DebugContext field normally contains the value zero. However, when you're debugging the thread's process, this field contains a pointer to a structure that contains register values and is similar to, but not the same as, the CONTEXT structure defined in WINNT.H.
however, reading JuneMouse's (thx) post, kernel code is clearly checking something else, dereferencing a pointer in kernel32.dll memory? seems that this pointer points into kernel (so called 'kernel' memory under win9x hehe, >= 0x80000000) memory.

Dno, after researching for 30 mins, i dont have enough motivation to add support for this ancient architecture :P
anyone who does, read this article: hxxp://www.microsoft.com/msj/archive/S2CE.aspx

Quote:

The 30h PVOID* pProcess field contains a linear address for the process database representing the process that owns the thread. However, this is not the same as a process handle or process ID.
however,there is no info on the PDB format there...

JuneMouse 03-01-2005 23:15

well what you posted about fs:[20] was documented some where in wasm.ru
when i searched

here is a snippet from there i had saved
Code:

mov    ecx,fs:[20h]
        jecxz  not_being_debugger

dunno never tried looking into it :) as i love my w2k :)

the article is here

http://wasm.ru/article.php?article=1017001


also there was some mention of fs:[60] in a japanese page

¡ºOllyDbg¡»¤¬±íʾ¤¹¤ë¡¸×îáá¤Î¥¨¥é©`¡¹¤Î¥¨¥é©`¥³©`¥É¤Ï¡¸FS:[34]¡¹(Win2k/XP)¤Þ¤¿¤Ï¡¸FS:[60]¡¹(Win9x/Me)¤Î‚Ž¤Ç¤¹¡£¤¿¤À¤·¡¢¤³¤Î¥¨¥é©`¥³©`¥É¤Î‚Ž¤¬GetLastErrorévÊý¤Î‘ø¤ê‚Ž¤ÈÒ»Ö¤·¤Ê¤¤¥±©`¥¹¤â¤¢¤ê¤Þ¤¹¡£ÌؤËWindows2000/XP¤Ç¤Î¤ßGetLastErrorévÊý¤Ç¥¨¥é©`¥³©`¥É¤òÈ¡µÃ¿ÉÄܤÊAPIévÊý¤Ë×¢

some more storage of info here is an url to the code i pasted
if some one want to test it in 9x

http://www.powerbasic.com/support/forums/Forum6/HTML/004517.html

Code:

Function IsDebuggerAttached() as Long
        Local vi As OSVERSIONINFO
        Local IsWin9x As Long
        Local Dw As Dword
        Local i  As Dword
  vi.dwOsVersionInfoSize = SizeOf(vi)
  GetVersionEx vi
  IsWin9x = ((vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS) And (vi.dwMinorVersion = 0)) Or _
            ((vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS) And (vi.dwMinorVersion <> 0))
  If IsWin9x Then
        !push eax                        '// Preserve the registers
        !mov eax, fs:[&h18]              '// Get the TIB's linear address
        !mov eax, dword ptr [eax + &h20] '// Debugger Contex for Win9x
        !mov dword ptr dw,  eax          '// Save it
        !pop eax                        '// Restore the registers
        If Dw Then
          Function = -1
        Else
          Function = 0
        End If
  Else
        !push eax                        '// Preserve the registers
        !push ecx
        !mov eax, fs:[&h18]              '// Get the TIB's linear address
        !mov eax, dword ptr [eax + &h30]
        !mov ecx, dword ptr [eax]        '// Get the whole DWORD
        !mov dword ptr dw,  ecx          '// Save it
        !pop ecx                        '// Restore the registers
        !pop eax
  '// The 3rd byte is the byte we really need to check for the
  '// presence of a debugger.
  '// Check the 3rd byte
      i= dw And &h00010000???
      If i Then
          Function = -1
      Else
          Function = 0
      End If
  End If


D-Jester 03-01-2005 23:47

Quote:

Originally Posted by upb
i dont have enough motivation to add support for this ancient architecture

This of course is becoming the norm. While prevelence of the 9x OS is still stifling despite its own creator no longer supporting it, whether to add support is really based on the targeted audience. Even if you don't add support you should still add OS detection for error prevention.

Quote:

Originally Posted by JuneMouse
also there was some mention of fs:[60] in a japanese page

babelfish Translation of : http://hp.vector.co.jp/authors/VA028184/OllyDbgQA.htm

"Thread Information Block (TIB)" with it is the local housing territory of the thread which is called. As for the first address of this data block making use of the segmented register, "FS: [ 18 ] "With it can acquire. Furthermore, with NT system OS originally this data block is called "Thread Environment Block (TEB)" with, but both between the reverse engineer is called TIB.

' OllyDbg ' it indicates as for "the error cord/code of" last error "FS: [ 34 ] "(Win2k/XP) or" FS: [ 60 ] "(Win9x/Me) it is value. However, there is also a case where value of this error cord/code does not match the return value of GetLastError function. With only especially Windows2000/XP the error cord/code please pay attention to acquisition possible API function with GetLastError function. Furthermore, don't you think? ' special frame is ¤Þ 57 ' the function which converts the error cord/code to the Japanese descriptive text is mounted, (inside "the application control" window).

By the way, with the main thread of ¥Ç¥Ð¥Ã¥®©` "FS: [ 04 ] "With" FS: [ 08 ] "The stacked area it is possible also from value to specify.

drizz 03-02-2005 05:01

Code:

; debug api test
;================
        mov eax,cs
        cmp ax,0FFh
        setg Is9x
        .if Is9x
                ;; structures are documented by EliCZ
                mov eax,fs:[20h];TIB.DebugContext
                test eax,eax
                setnz al
                or Detected,al
                mov ebx,fs:[30h];TIB.pParentPDB
                mov eax,[ebx+20h];[ebx].PDB.flags
                and eax,1;fDebugSingle equ 1
                or Detected,al
                mov eax,[ebx+54h];[ebx].PDB.DebuggeeCB  :IsDebuggerPresent
                test eax,eax
                setnz al
                or Detected,al
        .else
                ;; ddk
                mov eax,fs:[30h];TEB.pPEB        ; pointer to PEB
                movzx eax,byte ptr [eax+2];[eax].PEB.BeingDebugged  :IsDebuggerPresent
                or Detected,al
        .endif

you can't patch DebugContext in 9x
while BeingDebugged you can (upb's 1st post)

debug api in 9x suck
for example try to trace (single step)
not esp
not esp
*crash*

forget about 9x, support only NT (it's only a unpacker, unpacked exe must work on both)


All times are GMT +8. The time now is 17:14.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX