劳动节脑洞大开!利用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:// ...
随机推荐
- 15 Best Responsive HTML5 Frameworks 2014
Best HTML5 frameworks are most popular because with the use of these frameworks you can create websi ...
- JAVA 设计模式 享元模式
用途 享元模式 (Flyweight) 运用共享技术有效地支持大量细粒度的对象. 享元模式是一种结构型模式. 结构
- Android布局尺寸思考
一.初步思考 虽然安卓的这个显示适配的方案有点怪,最初也不容易马上理解,不过这个方案确实有其自己的道理,整个思路是清晰的,方案的也是完整的,没有硬伤 安卓采用的[屏幕密度放缩机制].与web前端对应的 ...
- 【转载】jquery validate验证插件,在ajax提交方式下的验证
正常的表单都是使用submit按钮来提交,jquery validate插件可以方便的做表单验证. 做一个发送短信的功能,向目标表插入多条记录,界面采用ajax来提交表单,等待效果直接用ext的遮罩 ...
- 百度地图API实现地图定位
1.引用JS: <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0& ...
- C#编程总结(十二)断点续传
C#编程总结(十二)断点续传 我们经常使用下载工具,如bit精灵.迅雷.FlashGet,这些软件都支持断点续传. 断点续传即下载任务暂停后可以继续,而无需重新下载,即下载时需要通知服务器的起始位置. ...
- Monotype推出基于HTML5的Web字体平台
著名字体公司Monotype近日宣布推出基于HTML5的Web字体平台,设计者可以访问近10万字体的目录. Monotype推出基于HTML5的Web字体平台 Monotype推出基于HTML5的We ...
- EF6 中tracking log使用方法总结
先上一段最近项目中的代码,此代码可以放到自己项目中的dbContext中 public override Task<int> SaveChangesAsync() { List<Au ...
- 【Java每日一题】20161130
20161129问题解析请点击今日问题下方的"[Java每日一题]20161130"查看 package Nov2016; public class Ques1130 { publ ...
- vim退出后终端保留 退出前的内容
export TERM=linux 或者 具体选项 可以看看secrecrt的选项