劳动节脑洞大开!利用Debug API 获取 加壳客户端的MD5值
系统 : Windows xp
程序 : 某游戏客户端
程序下载地址 :不提供
要求 : 远程注入 & 获取MD5值
使用工具 : vc++6.0 & OD
案例说明:
该游戏客户端对自身进行散列计算,并将md5值打包加密发给服务端。由于客户端本体带有病毒和压缩壳,索性采用硬件断点,和Debug API获取该MD5的内存地址。
逆向该客户端:
客户端启动时,先初始化md5内存:
00419DE4 B9 mov ecx,
00419DE9 33C0 xor eax, eax
00419DEB 8DBD B8610200 lea edi, dword ptr [ebp+261B8]
00419DF1 F3:AB rep stos dword ptr es:[edi] ; (initial cpu selection)
然后开始计算散列值:
004EA3E2 BE B8610200 mov esi, 261B8
004EA3E7 33D2 xor edx, edx
004EA3E9 8D45 EE lea eax, dword ptr [ebp-]
004EA3EC 8A543D B4 mov dl, byte ptr [ebp+edi-4C]
004EA3F0 push edx
004EA3F1 E06D5300 push 00536DE0 ; %02x
004EA3F6 push eax
004EA3F7 E8 ABEE0100 call 005092A7
004EA3FC 8B15 943C5400 mov edx, dword ptr [543C94]
004EA402 :8B4D EE mov cx, word ptr [ebp-]
004EA406 83C4 0C add esp, 0C
004EA409 inc edi
004EA40A :890C16 mov word ptr [esi+edx], cx
004EA40E 83C6 add esi,
004EA411 81FE D8610200 cmp esi, 261D8
004EA417 ^ 7C CE jl short 004EA3E7
跳出循环后,md5值就计算完毕了。我们利用DebugAPI模拟以上操作就可以。
但是要注意一点,传参 DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS调用CreateProcess函数会将exe占用。这时,程序打开自身的CreateFile函数将失败:
0012FC98 004EA381 /CALL to CreateFileA from xxx.004EA37F
0012FC9C 0012FCC4 |FileName = "xxx.exe"
0012FCA0 80000000 |Access = GENERIC_READ
0012FCA4 00000000 |ShareMode = 0
0012FCA8 00000000 |pSecurity = NULL
0012FCAC 00000003 |Mode = OPEN_EXISTING
0012FCB0 00000000 |Attributes = 0
0012FCB4 00000000 \hTemplateFile = NULL
解决办法很简单,将ShareMode改成FILE_SHARE_READ即可。
最后整理一下我们分析的结果:
1.对程序下硬件断点,保存md5的内存地址。
2.patch掉ShareMode,改为0x01(FILE_SHARE_READ)。
3.对计算完md5之后的指令下断,并读取md5.
部分实现代码:
//用于createprocess的两个参数
STARTUPINFO si;
PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO); char ReadBuffer[] = {};
bool WhileDoFlag = true; //创建进程
if ( !CreateProcess( FileName,NULL,NULL,NULL,FALSE,
DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS,NULL,NULL,&si,&pi ) ){
MessageBox( "打开程序失败!" ); DWORD dwRet = GetLastError();
CString strText(_T(""));
strText.Format(_T("%d"), dwRet);
AfxMessageBox("错误代码:"+strText); return ;
}
m_Pi = pi; DEBUG_EVENT DBEvent;
CONTEXT Regs;
DWORD dwSSCnt = ;
//存放md5地址
DWORD READ_ADDRESS; Regs.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS ; //设置程序在Single Step模式下执行
GetThreadContext( pi.hThread,&Regs );
Regs.EFlags |= 0x100;
SetThreadContext( pi.hThread,&Regs ); ResumeThread( pi.hThread ); while (WhileDoFlag) {
WaitForDebugEvent (&DBEvent, INFINITE);
switch (DBEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT: switch (DBEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_SINGLE_STEP :
{
++dwSSCnt ;
if (dwSSCnt == )
{
//当收到第一个EXCEPTION_SINGLE_STEP异常信号,表示中断在程序的第一条指令,即入口点
//把Dr0设置成程序的入口地址 GetThreadContext(pi.hThread,&Regs); Regs.Dr0=Regs.Eax;
Regs.Dr7=0x101; SetThreadContext(pi.hThread,&Regs); }
else if (dwSSCnt == )
{
//第二次中断在起先设置的入口点,在BP_MOLLC处设置硬件断点 GetThreadContext(pi.hThread, &Regs) ; Regs.Dr0 = BP_MOLLC;
Regs.Dr7 = 0x101 ; SetThreadContext(pi.hThread, &Regs) ;
}
else if (dwSSCnt == )
{
//第三次中断,己到指定的地址,读取EDI寄存器的数据
GetThreadContext(pi.hThread, &Regs) ; Regs.Dr0 = BP_INITMD5;
Regs.Dr7 = 0x101 ; READ_ADDRESS = Regs.Edi; BYTE NewMode = 0x01;
int a = WriteProcessMemory( pi.hProcess,(LPVOID)SET_SHAREMODE,&NewMode,, ); SetThreadContext(pi.hThread, &Regs) ; /*
//挂起进程
SuspendThread( pi.hThread );
//通知进程异常已处理
ContinueDebugEvent(DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE) ;
//卸载调试器
int a = _DebugSetProcessKillOnExit( FALSE );
int b = _DebugActiveProcessStop(DBEvent.dwProcessId);
//最后运行线程
ResumeThread( pi.hThread ); //int b = GetLastError();
WhileDoFlag=FALSE;
*/
}
else if (dwSSCnt == )
{
//第四次中断,MD5算出,读取数据.
GetThreadContext(pi.hThread, &Regs) ; Regs.Dr0 = Regs.Dr7 = ; ReadProcessMemory( pi.hProcess,(LPVOID)READ_ADDRESS,ReadBuffer,,NULL );
SetDlgItemText( IDC_EDITMD5,ReadBuffer ); SetThreadContext(pi.hThread, &Regs) ;
}
break;
}
}
break ; case EXIT_PROCESS_DEBUG_EVENT :
WhileDoFlag=FALSE;
break ;
}
//pi.dwProcessId和pi.dwThreadId 要改成如下的代码
ContinueDebugEvent(DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE) ;
} //.end while
劳动节脑洞大开!利用Debug API 获取 加壳客户端的MD5值的更多相关文章
- 我的Java开发学习之旅------>工具类:Java获取字符串和文件进行MD5值
ps:这几天本人用百度云盘秒传了几部大片到云盘上,几个G的文件瞬秒竟然显示"上传成功"!这真让我目瞪口呆,要是这样的话,那得多快的网速,这绝对是不可能的,也许这仅是个假象.百度了一 ...
- 如何获取Azure Storage Blob的MD5值
问题表述 直接使用CloudBlockBlob对象获取的Properties是空的,无法获取到对象的MD5值,后台并未进行属性值的填充 前提:blob属性本省包含md5值,某些方式上传的blob默认并 ...
- VS2008 C++ 利用WinHttp API获取Http请求/响应头部Header
http://www.cnblogs.com/LCCRNblog/p/3833472.html 这一篇博客中,实现了获取http请求/响应后的html源码,现在需要获取http请求/响应的头部Head ...
- VS2008 C++ 利用WinHttp API获取任意Http网址的源码
最近一直在看有关Http的知识,对其基本的理论知识已经有所掌握,想通过一个C++具体的例子进行实际操作..于是上网查找了很多资料,发现在Windows系统上,可以通过WinHttp API接口开啊Ht ...
- 爬虫——python——百度地图经纬度查询——经纬度查看地点地名——利用百度API获取地名经纬度——爬取所有的中国地址
import requests address = '40.8587960,86.866991' url = 'http://api.map.baidu.com/geocoder?output=jso ...
- 利用iOS API编写简单微博客户端全过程
要编写社交网络客户端程序,可以大体上分为4个主要的步骤 下面我们按照这个流程,介绍一下: 1.引入Accounts和Social框架 工 程中需要引入Accounts和Social框架,Account ...
- iOS开发,利用文件流,算大文件的MD5值(程序不会导致内存崩溃)
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath, size_t chunkSizeForReadingData) { // Dec ...
- jni中调用java方法获取当前apk的签名文件md5值
相应的java方法: void getsign(Context context) throws Exception { PackageInfo localPackageInfo = context.g ...
- PHP获取远程http或ftp文件的md5值
PHP获取本地文件的md5值: md5_file("/path/to/file.png"); PHP获取远程http文件的md5值: md5_file("https:// ...
随机推荐
- HTML5移动Web开发(三)——在移动网站中使用HTML5
创建一个简单得HTML5页面ch01e2.html <html> <head> <meta name="viewport" content=" ...
- 使用 CSS3 动感的图片标题动画效果【附源码下载】
在网站中,有很多地方会需要在图片上显示图片标题.使用 CSS3 过渡和变换可以实现动感的鼠标悬停显示效果.没有使用 JavaScript,所以只能在支持 CSS3 动画的现代浏览器中才能正常工作.您可 ...
- ffmpeg使用转码学习
ffmpeg在官网上描述自身:是一个对视频和音频进行记录,转换,流化的完整的跨平台解决方案.事实上,现在有很多工具都是基于ffmpeg来进行视频音频的处理工具的.比如鼎鼎大名的格式工厂,就是使用ffm ...
- C#实现通用数据过滤窗体
最近一直在做WINFORM项目,所以经常有些新的想法或尝试与大家分享,之前与大家分享了通用窗体遮罩层.通用可附加数据绑定的DataGridView.窗体渐显,今天来分享一个大家在其它软件中常见的功能: ...
- 《ASP.NET SignalR系列》第五课 在MVC中使用SignalR
接着上一篇:<ASP.NET SignalR系列>第四课 SignalR自托管(不用IIS) 一.概述 本教程主要阐释了如何在MVC下使用ASP.NET SignalR. 添加Signal ...
- View绘制过程理解
假期撸了几篇自定义View相关的东西,后两天下雨呆在家里还是效率太低Orz 每个Activity都包含一个Window对象,这个Window对象通常由PhoneWindow来实现[1],而每个Wi ...
- 解决matplotlib的中文问题
matplotlib的强大无需我去言说,但它对使用中文的我来说却有一点瑕疵,那就是--在默认状态下,matplotlb无法在图表中使用中文. 在网上查找了一些资料,发现matplotlib本身是支持U ...
- Apache+PHP 配置随笔
准备安装包 1:安装VC++ 2012(vcredist_x64,我这边服务器为64位) 2:Apache安装包,php安装包 安装后配置工作 1:安装Apache服务,配置环境变量 httpd -k ...
- Java总结篇系列:类型转换/造型
Java中,经常可以遇到类型转换的场景,从变量的定义到复制.数值变量的计算到方法的参数传递.基类与派生类间的造型等,随处可见类型转换的身影.Java中的类型转换在Java编码中具有重要的作用.首先,来 ...
- 用 Inkspace 做 SVG 给 TPath
FireMonkey 里的 TPathData 支持 SVG 的基本绘图指令,因此可以运用 Inkspace 软件,提取 SVG 的绘图内容,请见图片说明: