分析学习【1】—— Anti-debug分析及Snapshot学习

学着分析一个老样本的时候,发现了这个段anti-debug函数,鉴于WinSDK掌握不足,所以就慢慢分析了下。

概述:1、简单分析了这个anti-debug的流程;2、介绍下用到的Win函数,其中重点是如何获取运行中进程snapshot。

一、这个anti-debug非常老,如今OD的一堆插件绝对可以秒杀掉。只是简单的调用了"IsDebuggerPresent"函数,判断父进程,还有遍历所有进程判断是否有调试器(通过进程标题名称)。

1、LoadLibraryW函数原型(http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx)如下:

Syntax

HMODULE WINAPI LoadLibrary(
  __in  LPCTSTR lpFileName
);
w是Unicode版本的。该函数加载一个指定模块进入当前地址空间。因为被加载的模块可能依赖其它模块,所以,可能会同时加载其余模块。

2、GetProcAddress函数原型(http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx)如下:

Syntax

FARPROC WINAPI GetProcAddress(
  __in  HMODULE hModule,
  __in  LPCSTR lpProcName
);

返回指定DLL的输入函数或者变量地址。

代码如下:

.text:71001000
.text:71001000 ; Attributes: bp-based frame fpd=78h
.text:71001000
.text:71001000 Anti_debug      proc near               ; CODE XREF: kill_SecProcess+4Cp
.text:71001000                                         ; DllEntryPoint+11p ...
.text:71001000
.text:71001000 pe              = PROCESSENTRY32 ptr -128h
.text:71001000
.text:71001000                 push    ebp
.text:71001001                 lea     ebp, [esp-78h]
.text:71001005                 sub     esp, 128h
.text:7100100B                 push    ebx
.text:7100100C                 push    esi
.text:7100100D                 mov     esi, ds:LoadLibraryW
.text:71001013                 push    edi
.text:71001014                 push    offset ProcName ; "IsDebuggerPresent"
.text:71001019                 mov     ebx, offset LibFileName ; "kernel32.dll"
.text:7100101E                 push    ebx             ; lpLibFileName
.text:7100101F                 call    esi ; LoadLibraryW
.text:71001021                 mov     edi, ds:GetProcAddress ; 得到IsDebuggerPresent的地址
.text:71001027                 push    eax             ; hModule
.text:71001028                 call    edi ; GetProcAddress
.text:7100102A                 push    offset aGetcurrentproc ; "GetCurrentProcessId"
.text:7100102F                 push    ebx             ; lpLibFileName
.text:71001030                 mov     g_Kernel, eax
.text:71001035                 call    esi ; LoadLibraryW
.text:71001037                 push    eax             ; hModule
.text:71001038                 call    edi ; GetProcAddress
.text:7100103A                 xor     edi, edi
.text:7100103C                 push    edi             ; th32ProcessID
.text:7100103D                 push    2               ; dwFlags
.text:7100103F                 mov     ebx, eax
.text:71001041                 call    CreateToolhelp32Snapshot
.text:71001046                 mov     esi, eax
.text:71001048                 lea     eax, [ebp+78h+pe]
.text:7100104E                 push    eax             ; lppe
.text:7100104F                 push    esi             ; hSnapshot
.text:71001050                 mov     [ebp+78h+pe.dwSize], 128h
.text:7100105A                 call    Process32First
.text:7100105F
.text:7100105F DO_BEGIN:                               ; CODE XREF: Anti_debug+78j
.text:7100105F                 call    ebx
.text:71001061                 cmp     [ebp+78h+pe.th32ProcessID], eax ; 获得本进程信息
.text:71001067                 jz      short Break     ; 检测父进程ID
.text:71001069                 lea     eax, [ebp+78h+pe]
.text:7100106F                 push    eax             ; lppe
.text:71001070                 push    esi             ; hSnapshot
.text:71001071                 call    Process32Next
.text:71001076                 test    eax, eax
.text:71001078                 jnz     short DO_BEGIN
.text:7100107A                 jmp     short loc_71001094
.text:7100107C ; ---------------------------------------------------------------------------
.text:7100107C
.text:7100107C Break:                                  ; CODE XREF: Anti_debug+67j
.text:7100107C                 mov     edi, [ebp+78h+pe.th32ParentProcessID] ; 检测父进程ID
.text:71001082                 cmp     edi, 4          ; 如果父进程System进程,表明正常运行
.text:71001085                 jz      Security        ; 安全,没有被调试
.text:7100108B                 cmp     edi, 8          ; ID号为8的是哪个进程
.text:7100108E                 jz      Security
.text:71001094
.text:71001094 loc_71001094:                           ; CODE XREF: Anti_debug+7Aj
.text:71001094                 lea     eax, [ebp+78h+pe]
.text:7100109A                 push    eax             ; lppe
.text:7100109B                 push    esi             ; hSnapshot
.text:7100109C                 call    Process32First  ; 再次检测当前进程
.text:710010A1
.text:710010A1 loc_710010A1:                           ; CODE XREF: Anti_debug+14Aj
.text:710010A1                 cmp     [ebp+78h+pe.th32ProcessID], edi
.text:710010A7                 jnz     loc_7100113B
.text:710010AD                 lea     eax, [ebp+78h+pe.szExeFile]
.text:710010B3                 push    eax             ; int
.text:710010B4                 push    offset String   ; "OllyDbg.exe"
.text:710010B9                 call    Is_EqualString
.text:710010BE                 test    eax, eax
.text:710010C0                 pop     ecx
.text:710010C1                 pop     ecx
.text:710010C2                 jz      Security
.text:710010C8                 lea     eax, [ebp+78h+pe.szExeFile]
.text:710010CE                 push    eax             ; int
.text:710010CF                 push    offset aOllyice_exe ; "OllyICE.exe"
.text:710010D4                 call    Is_EqualString
.text:710010D9                 test    eax, eax
.text:710010DB                 pop     ecx
.text:710010DC                 pop     ecx
.text:710010DD                 jz      short Security
.text:710010DF                 lea     eax, [ebp+78h+pe.szExeFile]
.text:710010E5                 push    eax             ; int
.text:710010E6                 push    offset aPeditor_exe ; "PEditor.exe"
.text:710010EB                 call    Is_EqualString
.text:710010F0                 test    eax, eax
.text:710010F2                 pop     ecx
.text:710010F3                 pop     ecx
.text:710010F4                 jz      short Security
.text:710010F6                 lea     eax, [ebp+78h+pe.szExeFile]
.text:710010FC                 push    eax             ; int
.text:710010FD                 push    offset aLordpe_exe ; "LordPE.exe"
.text:71001102                 call    Is_EqualString
.text:71001107                 test    eax, eax
.text:71001109                 pop     ecx
.text:7100110A                 pop     ecx
.text:7100110B                 jz      short Security
.text:7100110D                 lea     eax, [ebp+78h+pe.szExeFile]
.text:71001113                 push    eax             ; int
.text:71001114                 push    offset aC32asm_exe ; "C32Asm.exe"
.text:71001119                 call    Is_EqualString
.text:7100111E                 test    eax, eax
.text:71001120                 pop     ecx
.text:71001121                 pop     ecx
.text:71001122                 jz      short Security
.text:71001124                 lea     eax, [ebp+78h+pe.szExeFile]
.text:7100112A                 push    eax             ; int
.text:7100112B                 push    offset aImportrec_exe ; "ImportREC.exe"
.text:71001130                 call    Is_EqualString
.text:71001135                 test    eax, eax
.text:71001137                 pop     ecx
.text:71001138                 pop     ecx
.text:71001139                 jz      short Security
.text:7100113B
.text:7100113B loc_7100113B:                           ; CODE XREF: Anti_debug+A7j
.text:7100113B                 lea     eax, [ebp+78h+pe]
.text:71001141                 push    eax             ; lppe
.text:71001142                 push    esi             ; hSnapshot
.text:71001143                 call    Process32Next
.text:71001148                 test    eax, eax
.text:7100114A                 jnz     loc_710010A1
.text:71001150                 call    g_Kernel
.text:71001156                 test    eax, eax
.text:71001158                 pop     edi
.text:71001159                 pop     esi
.text:7100115A                 pop     ebx
.text:7100115B                 jz      short loc_71001165
.text:7100115D
.text:7100115D Security:                               ; CODE XREF: Anti_debug+85j
.text:7100115D                                         ; Anti_debug+8Ej ...
.text:7100115D                 push    0               ; uExitCode
.text:7100115F                 call    ds:ExitProcess
.text:71001165 ; ---------------------------------------------------------------------------
.text:71001165
.text:71001165 loc_71001165:                           ; CODE XREF: Anti_debug+15Bj
.text:71001165                 xor     eax, eax
.text:71001167                 add     ebp, 78h
.text:7100116A                 leave
.text:7100116B                 retn
.text:7100116B Anti_debug      endp ; sp-analysis failed
.text:7100116B
.text:7100116C


二、这个snapshot术语刚刚接触到,值得学习。

(另一种获取当前进程信息方法在博文http://blog.csdn.net/betabin/article/details/7483939)

1、接触PROCESSENTRY32结构,其原型如下:

Syntax

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;

w是Unicode版本,这个PROCESSENTRY32是Ansi版本。

这个结构是用于进行快照时,描述一个驻留于系统地址空间的进程列表。其中size在使用前要初始化为sizeof(PROCESSENTRY32)。

2、至于接下来的Process32First函数,则是开始遍历进程了。原型如下:

Syntax

BOOL WINAPI Process32First(
  __in     HANDLE hSnapshot,
  __inout  LPPROCESSENTRY32 lppe
);


也果断摘录了MSDN里的一个例程代码如下:

#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>

//  Forward declarations:
BOOL GetProcessList( );
BOOL ListProcessModules( DWORD dwPID );
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );

int main( void )
{
  GetProcessList( );
  return 0;
}

BOOL GetProcessList( )
{
  HANDLE hProcessSnap;
  HANDLE hProcess;
  PROCESSENTRY32 pe32;
  DWORD dwPriorityClass;

  // Take a snapshot of all processes in the system.
  hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
  if( hProcessSnap == INVALID_HANDLE_VALUE )
  {
    printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
    return( FALSE );
  }

  // Set the size of the structure before using it.
  pe32.dwSize = sizeof( PROCESSENTRY32 );

  // Retrieve information about the first process,
  // and exit if unsuccessful
  if( !Process32First( hProcessSnap, &pe32 ) )
  {
    printError( TEXT("Process32First") ); // show cause of failure
    CloseHandle( hProcessSnap );          // clean the snapshot object
    return( FALSE );
  }

  // Now walk the snapshot of processes, and
  // display information about each process in turn
  do
  {
    _tprintf( TEXT("\n\n=====================================================" ));
    _tprintf( TEXT("\nPROCESS NAME:  %s"), pe32.szExeFile );
    _tprintf( TEXT("\n-------------------------------------------------------" ));

    // Retrieve the priority class.
    dwPriorityClass = 0;
    hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
    if( hProcess == NULL )
      printError( TEXT("OpenProcess") );
    else
    {
      dwPriorityClass = GetPriorityClass( hProcess );
      if( !dwPriorityClass )
        printError( TEXT("GetPriorityClass") );
      CloseHandle( hProcess );
    }

    _tprintf( TEXT("\n  Process ID        = 0x%08X"), pe32.th32ProcessID );
    _tprintf( TEXT("\n  Thread count      = %d"),   pe32.cntThreads );
    _tprintf( TEXT("\n  Parent process ID = 0x%08X"), pe32.th32ParentProcessID );
    _tprintf( TEXT("\n  Priority base     = %d"), pe32.pcPriClassBase );
    if( dwPriorityClass )
      _tprintf( TEXT("\n  Priority class    = %d"), dwPriorityClass );

    // List the modules and threads associated with this process
    ListProcessModules( pe32.th32ProcessID );
    ListProcessThreads( pe32.th32ProcessID );

  } while( Process32Next( hProcessSnap, &pe32 ) );

  CloseHandle( hProcessSnap );
  return( TRUE );
}


BOOL ListProcessModules( DWORD dwPID )
{
  HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
  MODULEENTRY32 me32;

  // Take a snapshot of all modules in the specified process.
  hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
  if( hModuleSnap == INVALID_HANDLE_VALUE )
  {
    printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
    return( FALSE );
  }

  // Set the size of the structure before using it.
  me32.dwSize = sizeof( MODULEENTRY32 );

  // Retrieve information about the first module,
  // and exit if unsuccessful
  if( !Module32First( hModuleSnap, &me32 ) )
  {
    printError( TEXT("Module32First") );  // show cause of failure
    CloseHandle( hModuleSnap );           // clean the snapshot object
    return( FALSE );
  }

  // Now walk the module list of the process,
  // and display information about each module
  do
  {
    _tprintf( TEXT("\n\n     MODULE NAME:     %s"),   me32.szModule );
    _tprintf( TEXT("\n     Executable     = %s"),     me32.szExePath );
    _tprintf( TEXT("\n     Process ID     = 0x%08X"),         me32.th32ProcessID );
    _tprintf( TEXT("\n     Ref count (g)  = 0x%04X"),     me32.GlblcntUsage );
    _tprintf( TEXT("\n     Ref count (p)  = 0x%04X"),     me32.ProccntUsage );
    _tprintf( TEXT("\n     Base address   = 0x%08X"), (DWORD) me32.modBaseAddr );
    _tprintf( TEXT("\n     Base size      = %d"),             me32.modBaseSize );

  } while( Module32Next( hModuleSnap, &me32 ) );

  CloseHandle( hModuleSnap );
  return( TRUE );
}

BOOL ListProcessThreads( DWORD dwOwnerPID ) 
{ 
  HANDLE hThreadSnap = INVALID_HANDLE_VALUE; 
  THREADENTRY32 te32; 
 
  // Take a snapshot of all running threads  
  hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); 
  if( hThreadSnap == INVALID_HANDLE_VALUE ) 
    return( FALSE ); 
 
  // Fill in the size of the structure before using it. 
  te32.dwSize = sizeof(THREADENTRY32); 
 
  // Retrieve information about the first thread,
  // and exit if unsuccessful
  if( !Thread32First( hThreadSnap, &te32 ) ) 
  {
    printError( TEXT("Thread32First") ); // show cause of failure
    CloseHandle( hThreadSnap );          // clean the snapshot object
    return( FALSE );
  }

  // Now walk the thread list of the system,
  // and display information about each thread
  // associated with the specified process
  do 
  { 
    if( te32.th32OwnerProcessID == dwOwnerPID )
    {
      _tprintf( TEXT("\n\n     THREAD ID      = 0x%08X"), te32.th32ThreadID ); 
      _tprintf( TEXT("\n     Base priority  = %d"), te32.tpBasePri ); 
      _tprintf( TEXT("\n     Delta priority = %d"), te32.tpDeltaPri ); 
      _tprintf( TEXT("\n"));
    }
  } while( Thread32Next(hThreadSnap, &te32 ) ); 

  CloseHandle( hThreadSnap );
  return( TRUE );
}

void printError( TCHAR* msg )
{
  DWORD eNum;
  TCHAR sysMsg[256];
  TCHAR* p;

  eNum = GetLastError( );
  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, eNum,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
         sysMsg, 256, NULL );

  // Trim the end of the line and terminate it with a null
  p = sysMsg;
  while( ( *p > 31 ) || ( *p == 9 ) )
    ++p;
  do { *p-- = 0; } while( ( p >= sysMsg ) &&
                          ( ( *p == '.' ) || ( *p < 33 ) ) );

  // Display the message
  _tprintf( TEXT("\n  WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
}


你可能感兴趣的:(thread,Module,exe,attributes,structure,winapi)