[Translation] The Other Ways To Detect OLLYDBG Detects OLLYDBG alternative
This is the Linhanshi brother is placed on his website. I feel that I translated it, the level is very bad, and you will bear! The Other Ways To Detect OLLYDBG Detects OLLYDBG Other Method PUMQARA WITS / ROBA [TT] Translated In 2004, Ring-3 debuggers are increasingly used because they have graphical interfaces and rather than Ring-0 Class debugger (such as Softice) is more convenient. In this article I will tell one of the best Ring-3 debuggers - Allydbg. Many people have heard of ISDebugerPresent and FS: [20] detection means, but have other new methods? Below I introduce you some of my own testing methods. I will give a detailed explanation, so you can use your own imagination to improve them. Method 1: The method of findwindow is based on the FindWindow function. Like all dialogs, OLLYDBG's master dialog (window?) Also has its title and class name. Using this API function We can determine if the main window of the OLLYDBG is open. Microsoft wrote this: --------------------------------------------- -------------------------------------------------- The -findWindow function gets a handle of a window class name or a top window of a particular string. This function does not search with the child window. HWND FINDWINDOW (LPCTSTSTSTSTSTSNAME, / / Address LPCTSTR LPWINDOWNAME / / Window Title Address); Parameter Description LPClassName points to a pointer to a string of the name of the window class name, or an identity window class name character ATOM of the string. If this parameter is an atom, it must be a global Atom for the pre-established function GlobalAddatom. This 16-bit Atom must be placed at the low of LPClassName, and the high 8 bits of LPClassName must be 0. LPWindownAme points to a pointer to a string of a window name (ie, title) ending at NULL. If this parameter is NULL, all windows are considered to be in line with the conditions. Return Value If the search is successful, return to the found eligible window handle. If the search fails, the return value is NULL. To get a detailed error message, you can call GetLastError. -------------------------------------------------- ---------------------------------------------- My program :
Code:
.DATA
StrollyClsname DB "OLLYDBG", 0
.code
Invoke Findwindow, Addr StrollyClsname, Null
CMP EAX, 0000000000H
JNE OLLY_DETECTED /
Method 2: CreateToolHelp32Snapshot, Process32First / Next This is an interesting approach. It is based on four API functions (CreateToolhelp32Snapshot, Process32First, Process 32Next, GetCurrentProcessid) and a structure (Processentry32). Let's take a look at MSDN: ----------------------------------------- -------------------------------------------------- --- [CreateToolHelp32Snapshot] CreateToolHelp32Snapshot function is a specified process (you can include a heap [HEAP], module [Module], and thread [thread], which can be used [HEAP], module [Module], and thread [THREAD]]. Handle WinAPI CreateToolHelp32Snapshot (DWORD DWFLAGS, DWORD TH32PROCESSID); Parameter Description: DWFLAGS [Enter] TH32CS_INHERIT - Declaration The snap handle is inherited. Th32CS_SNAPALL - contains all processes and threads in the snapshot, and includes all piles of the plots and modules TH32CS_SNAPHEAPLIST specified in TH32ProcessID - all piles included in the TH32ProcessID in the snapshot. To list the pile of the process, check the Heap32ListFirst. TH32CS_SNAPModule - All modules included in the process specified in the TH32ProcessID in the snapshot. To list the modules of the process, see Module32ListFirst. TH32CS_SNAPPROCESS - contains all the processes in the system in the snapshot. To list all processes, check out Process32First.th32cs_snapthread - contains all threads in the system in the snapshot. To list all threads, see Thread32First.th32ProcessID [Input] Specifies the process ID to be captured. If this parameter is 0, it is 0 to grab the current process. This parameter is only valid after setting TH32CS_SNAPHEAPLIST, TH32CS_SNAPMOUDLE or TH32CS_SNAPALL, and this parameter is ignored in other cases, all processes are captured. Return Values If the call is successful, return to the snapshot handle. Returns Invaid_Handle_Value if the call fails. RemarksThe snapshot taken by this function is examined by the other tool help functions to provide their results. Access to the snapshot is read only. The snapshot handle acts like an object handle and is subject to the same rules regarding which processes and threads it is valid To list the stacks and module status of all processes, specify TH32CS_SNAPALL and set Th32ProcessI to 0. Then, for each new process in the snapshot, call CreateToolHelp32Snapshot again, set the new process ID and TH32CS_SNAPHEAPLIST or TH32CS_SNAPHEAPLIST or TH32CS_SNAPMOULE to be captured. To delete a snapshot, use the CloseHandle function.
-------------------------------------------------- ---------------------------------------------- [Process32First] Process32First Get information on the first process in a system snapshot. BOOL WINAPI Process32First (HANDLE hSnapshot, LPPROCESSENTRY32 lppe); Parameter Description lppe returned when the handle hSnapshot [in] a previous call to the function pointing system snapshot CreateToolhelp32Snapshot [input, out] Pointer to a structure PROCESSENTRY32 return value if the first list of processes The entrance has been copied into the buffer, and returns false. If the process information is not included in the snapshot, an error_no_more_files error will be returned via getLastError. Remarks The program that calls this function must set the member dwsize in Processentry32 to the size of the structure (represented by byte). Process32First will change DWSIZE to the number of bytes written to the structure. This value will never be larger than the initial value of dwsize, but it may be smaller. If this value is smaller, any member of any offset greater than this value is unreliable. To get information about other processes in the same snapshot, use the Process32Next function. -------------------------------------------------- ---------------------------------------------- [Process32Next] Process32Next You can get information in a system snapshot. BOOL WINAPI Process32Next (HANDLE hSnapshot, LPPROCESSENTRY32 lppe); handle returned Parameter Description hSnapshot [in] a previous call CreateToolhelp32Snapshot function pointing system snapshot LPPe [out] Pointer to a PROCESSENTRY32 configuration of the return value, if the next entry in the list of processes have been Returns true in the copy to the buffer, otherwise returns false. If the process information is not included in the snapshot, an error_no_more_files error will be returned via getLastError. Note To get information about the first process in a snapshot, use the Process32First function. -------------------------------------------------- ---------------------------------------------- [Processentry32] After a snapshot is established, Processentry32 describes one of a series of processes in the system address space. The number of member variables dwSize bytes; typedef struct tagPROCESSENTRY32 {DWORD dwSize; DWORD cntUsage; DWORD th32ProcessID; ULONG_PTR th32DefaultHeapID; DWORD th32ModuleID; DWORD cntThreads; DWORD th32ParentProcessID; LONG pcPriClassBase; DWORD dwFlags; TCHAR szExeFile [MAX_PATH];} PROCESSENTRY32, * PPROCESSENTRY32 The structure of the representation is indicated. Before calling Process32First, set this member to SIZEOF (Processentry32). If you don't initialize DWSIZE, Process32First will call failed. CNTUSAGE This process is referenced. Only one process is not 0, this process exists. Once its reference is 0, the process is terminated. TH32ProcessID The logo of this process.
(ID) th32DefaultHeapID Identifier of the default heap for the process. The contents of this member has meaning only to the tool help functions. It is not a handle, nor is it usable by functions other than the ToolHelp functions. Th32ModuleID Module identifier of the Process. The Contents of this Member Has Meaning Only To The Tool Help Functions. It is not a handle, nor is it usable by functions. CNTTHREALP FUNCTION. CNTTHREADS The number of threads started by the process. TH32ParentProcessID creates the identity of the parent process of the process. PCPriclassBase Base Priority of Any Threads Created by this process. dwflags is not used, retain szexefile points to a pointer to a string ended with NULL, which illustrates the executable file to which the process belongs. In Windows ME / 98/95, this file name contains a path. -------------------------------------------------- ---------------------------------------------- [GetCurrentProcessid] getCurrentProcessID Returns the identity of the process that calls the function. DWORD GETCURRENTPROCESSID (VOID) Parameter Description: This function has no parameters. The return value returns the value of the process of calling the function. Remarks This Process Number (ID) determines a unique process in the system until the process terminates. -------------------------------------------------- ----------------------------------------------our target is Detecting the parent process of our program is OLLYDBG. Plan: 1. Use getCurrentProcessID to get the process ID of our program. 2.) Use CreateToolhelp32Snapshot and Process32First / next to compare the Th32ProcessID member in each Processentry32 structure is our process ID until it is found. 3.) Get the TH32ParentProcessID in the Processentry32 structure. (Demolition: The Parent Process ID) 4.) Start a new round of comparison with CreateToolHelp32Snapshot, but this time is the ID of each TH32Processid member is the ID of the parent process you get in step 3 until you find out. 5.) Get the SZEXEFILE member in Processentry32, see if it is "OLLYDBG.EXE" 6.) If so, we know that our program is running under OllyDBG control. Sample code: Code:
.586
.Model flat, stdcall
Option CaseMAP: NONE
Include D: /masm32/include/windows.inc
INCLUDE D: /MASM32/INCLUDE/USER32.INC
INCLUDE D: /MASM32/INCLUDE/kernel32.inc
IncludeLib D: /masm32/lib/user32.lib
Includelib D: /masm32/lib/kernel32.lib.data
STRCAPTION DB "OLLYDBG DETECTOR!", 0
Strfound DB "Ollydbg Found!", 0
STRNOTFOUND DB "OLLYDBG NOT FOUND!", 0
StrollyDBG DB "OLLYDBG.EXE", 0H
VALCURRENTPID DD 0
ValparentPid DD 0
HSnapshot DD 0
.DATA?
Proces Processentry32 <>
.code
Start:
Establish snapshot
Invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, NULL
Mov HSnapshot, EAX
; Get the current process ID
Invoke getCurrentProcessID
Mov ValcurrentPid, EAX
Lea ESI, Offset Proces
Assume ESI: Ptr Processentry32
MOV [ESI] .dwsize, sizeof processentry32
Start the first round of search
; Look for current processes with ValcurrentPid
Invoke Process32First, HSnapshot, Addr Proces
Lea ESI, Offset Proces
Assume ESI: Ptr Processentry32
MOV EBX, VALCURRENTPID
CMP EBX, [ESI] .th32Processid
JNE NOPE1
NOPE1:
Invoke Process32Next, HSnapshot, Addr Proces
Lea ESI, Offset Proces
Assume ESI: Ptr Processentry32
MOV EBX, VALCURRENTPID
CMP EBX, [ESI] .th32Processid
JNE NOPE1
Push [ESI] .th32parentProcessid
POP ValparentPid
Invoke Closehandle, HSnapshot
Establish snapshot again
Invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, NULL
Mov HSnapshot, EAX
MOV [ESI] .dwsize, sizeof processentry32
Start the second round of search
; Find the parent process of the current process using ValparentPid
Invoke Process32First, HSnapshot, Addr Proces
Lea ESI, Offset Proces
Assume ESI: Ptr Processentry32
MOV EBX, ValparentPid
CMP EBX, [ESI] .th32Processid
JNE NOPE2
NOPE2:
Invoke Process32Next, HSnapshot, Addr Proces
Lea ESI, Offset Proces
Assume ESI: Ptr Processentry32
MOV EBX, ValparentPid
CMP EBX, [ESI] .th32Processid
JNE NOPE2
; Extract the file name from the full path
Lea Eax, [ESI] .szexefile
Push EAX
Invoke lstrlen, EAX
Sub Eax, 11
POP EBX
Add Ebx, EAX
; Turn the file name into uppercase, compare with "ollydbg.exe"
Invoke Charupper, EBX
Invoke Lstrcmp, EBX, Addr Strollydbg
.IF EAX == 0
Invoke Messagebox, 0, Addr strfound, Addr strcaption, 0.else
Invoke Messagebox, 0, AddR Strnotfound, Addr strcaption, 0
.Endif
Invoke Closehandle, HSnapshot
Invoke EXITPROCESS, 0
End Start
Method 3: SetunHandledExceptionFilter (Mode Note: About SEH in the << SEH IN ASM >> article one article has a classic discussion, omitted here, only listing code, please refer to English Original and << SEH IN ASM >>
Code:
.586
.Model flat, stdcall
Option CaseMAP: NONE
Include D: /masm32/include/windows.inc
INCLUDE D: /MASM32/INCLUDE/USER32.INC
INCLUDE D: /MASM32/INCLUDE/kernel32.inc
IncludeLib D: /masm32/lib/user32.lib
IncludeLib D: /masm32/lib/kernel32.lib
.DATA
STRCAPTION DB "OLLYDBG DETECTOR", 0
STRNOTFOUND DB "OLLYDBG NOT FOUND!", 0
.code
Excphandler Proc
MOV Eax, DWORD PTR [ESP 4]; EAX = Exception_Pointers
Mov Eax, [EAX 4]; EAX = Context
Assume EAX: PTR Context
MOV [EAX] .regEIP, OFFSET SAFE_ADDRESS; Change Regeip
Pushhad
Invoke Messagebox, 0, AddR Strnotfound, Addr strcaption, 0
Popad
XOR EAX, EAX; /
;) SET EXCEPTION_CONTINUE_EXECUTION
Dec EAX; /
Retn 4; Normalize Stack and Return
EXCPHANDLER ENDP
Start:
Invoke setunhandledExceptionFilter, Offset Excphandler
MOV EBX, DWORD PTR [0FFFFFFFH]; Exception is here!
SAFE_ADDRESS:
Invoke EXITPROCESS, 0
End Start
Method 4: API relocation This is a method I discovered by myself, which is based on the processing method when the OLLYDBG is called the API function. When the debugging program is called, Oleh Yuschuk (author of Ollydbg) is handled by using the API relocation method in his debugger. Let's take a look at: 0401000> Push asd.00403033; / filename = "kernel32.dll" 00401005 Call; / loadLibrarya || '-> 0040105C JMP DWORD PTR DS: [402004]; JMP DWORD PTR DS: [<& kernel32. LoadLibrarya>] || '-> 87ff4120 push bff776d0; push kernel32.loadLibraryA87FF4125 JMP kernel32.bff957ca looks manually loaded the input table and manually fills IAT, all API addresses are reset into a hidden buffer . In this buffer, he calls a function in a strange way. But for us, there is a more important issue: he also imitates the getProcAddress function, so this function returns the address after the relocation. For example, the actual address of IsDebuggerPresent in memory is BFF946F6, but this function returns to the address 87FF4110 after the relocation. How do we use this to implement OLLYDBG detection? Well, there are many ways, the following is the shortest type: 1.) Load the kernel32.dll library, then return its base address (which is loaded into memory) 2.) Call the getProcAddress function to get the address of EXITPROCESS 3.) Comparison of the base address of the above return value (EXITPROCESS obtained by getProcaddress) and the base address of Kernel32.dll 4.) If this return value (step 2 is income) is greater than the base address (step 1), we can Affirm this API function is called directly, otherwise this API is indirectly called. Sample program: Code:
.586
.Model flat, stdcall
Option CaseMAP: NONE
Include D: /masm32/include/windows.inc
INCLUDE D: /MASM32/INCLUDE/USER32.INC
INCLUDE D: /MASM32/INCLUDE / Kenel32.inc
IncludeLib D: /masm32/lib/user32.lib
IncludeLib D: /masm32/lib/kernel32.lib
.DATA
STRCAPTION DB "OLLYDBG DETECTOR", 0
Strfound DB "Ollydbg Found!", 0
STRNOTFOUND DB "OLLYDBG NOT FOUND!", 0
Strlibrary DB "kernel32.dll", 0
Strfunction DB "EXIXTPROCESS", 0
.code
Start:
Invoke Loadlibrary, Addr Strlibrary, ADDR STRLIBRARY
Push Eax; EAX is the base address for kernel32.dll
Invoke GetProcaddress, Eax, Addr Strfunction
; Eax is the address of EXITPROCESS or after relocation
POP EBX; EBX is the base address of kernel32.dll
CMP EAX, EBX; Whether EXITPROCESS address Invoke Messagebox, 0, AddR Strnotfound, Addr strcaption, Null Invoke EXITPROCESS, 0 OLLY_DETECTED: Invoke Messagebox, 0, Addr strfound, Addr strcaption, null Invoke EXITPROCESS, 0 End Start Conclusion: I hope you like this article. I wish you good luck, Pumqara. Translator Review: This article proposes four methods for detecting OLLYDBG. The first one should be the simplest and most common, the third method is also involved in the book of SEH in the book, but the second and the first The four ways are very novel, and only when the program is being commissioned, it will be "humanized", not like the FindWindow or traditional tradition process, find that there is a debugger, no matter what people do, pull out : D. Originally, I'm going to read it after I tossed, I couldn't be clear, and I couldn't be clear, and the translation is more chaotic. Which one can help it. It seems that you have to study hard in the future and improve the level. Thank Linhanshi Brother to provide this article, thank you for your patience. :)