劳动节脑洞大开!利用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:// ...
随机推荐
- Fragment响应返回键
Activty可以直接响应返回键,而Fragment却不行,可用如下方式: 创建一个抽象类BackHandledFragment,该类中有一个抽象方法onBackPress(),所有BackHandl ...
- [转载]UML时序图总结
前言 在我的工作中,用的最多的就是时序图了.可能由于工作的原因,我也是最喜欢画时序图了,很清楚,很明了,什么时候发送什么消息,到达什么状态,一下子就展示在你的脑海里,对于消息驱动的程序来说,是再好不过 ...
- Windows GUI代码与Windows消息问题调试利器
Windows GUI代码与Windows消息问题调试利器 记得很久前有这么一种说法: 人类区别于动物的标准就是工具的使用.同样在软件开发这个行业里面,对于工具的使用也是高手和入门级选手的主要区别,高 ...
- position属性absolute与relative 详解
最近一直在研究javascript脚本,熟悉DOM中CSS样式的各种定位属性,以前对这个属性不太了解,从网上找到两篇文章感觉讲得很透彻,收藏下来,唯恐忘记.一.解读absolute与relative ...
- 这些HTML、CSS知识点,面试和平时开发都需要 No5-No7
系列知识点汇总 这些HTML.CSS知识点,面试和平时开发都需要 No1-No4(知识点:HTML.CSS.盒子模型.内容布局) 这些HTML.CSS知识点,面试和平时开发都需要 No5-No7(知识 ...
- Mac下github项目检出与提交
项目检出 如果你的git还没有代码仓库,可以用过git的代码仓库页面新建一个你的仓库 创建git上的仓库后,我们还需要建立本地的仓库,所以打开Mac终端,建立本地仓库文件夹(这里我用HelloC),然 ...
- JS虚拟键盘
由于是触摸屏,所以需要一款JS虚拟键盘.上网找了一个好用的VirtualKeyboard,作了修改. 修改该插件参考的博客文章:http://www.cnblogs.com/xinggong/arch ...
- jquery-easyui-tree异步树
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- Stream转MemoryStream解决Stream.Length报错此流不支持查找操作
1.StreamToMemoryStream MemoryStream StreamToMemoryStream(Stream instream) { MemoryStream outstream = ...
- MEF入门之不求甚解,但力求简单能讲明白(二)
在上一篇文章中,我们已经学到了很基本的MEF概念和使用方法. 但我们导出的是一个object类型的实例,只能用来tostring,没有引用部件类库,也不能用里面的成员方法. 本篇,我们逐渐往简单的文件 ...