热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

劳动节脑洞大开!利用DebugAPI获取加壳客户端的MD5值

系统:Windowsxp程序:某游戏客户端程序下载地址:不提供要求:远程注入&获取MD5值使用工具:vc++6.0&OD案例说明:该游戏客户端对自身进行散

系统 : Windows xp

程序 : 某游戏客户端

程序下载地址 :不提供

要求 : 远程注入 & 获取MD5值

使用工具 : vc++6.0 & OD

 

案例说明:

该游戏客户端对自身进行散列计算,并将md5值打包加密发给服务端。由于客户端本体带有病毒和压缩壳,索性采用硬件断点,和Debug API获取该MD5的内存地址。

 

逆向该客户端:

客户端启动时,先初始化md5内存:

00419DE4    B9 08000000     mov     ecx, 8
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-12]
004EA3EC 8A543D B4 mov dl, byte ptr [ebp+edi-4C]
004EA3F0 52 push edx
004EA3F1 68 E06D5300 push 00536DE0 ; %02x
004EA3F6 50 push eax
004EA3F7 E8 ABEE0100 call 005092A7
004EA3FC 8B15 943C5400 mov edx, dword ptr [543C94]
004EA402 66:8B4D EE mov cx, word ptr [ebp-12]
004EA406 83C4 0C add esp, 0C
004EA409 47 inc edi
004EA40A 66:890C16 mov word ptr [esi+edx], cx
004EA40E 83C6 02 add esi, 2
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[128] = {0};
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
= 0;
//存放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 == 1)
{
//当收到第一个EXCEPTION_SINGLE_STEP异常信号,表示中断在程序的第一条指令,即入口点
//把Dr0设置成程序的入口地址

GetThreadContext(pi.hThread,
&Regs);

Regs.Dr0
=Regs.Eax;
Regs.Dr7
=0x101;

SetThreadContext(pi.hThread,
&Regs);

}
else if (dwSSCnt == 2)
{
//第二次中断在起先设置的入口点,在BP_MOLLC处设置硬件断点

GetThreadContext(pi.hThread,
&Regs) ;

Regs.Dr0
= BP_MOLLC;
Regs.Dr7
= 0x101 ;

SetThreadContext(pi.hThread,
&Regs) ;
}
else if (dwSSCnt == 3)
{
//第三次中断,己到指定的地址,读取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,1,0 );

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 == 4)
{
//第四次中断,MD5算出,读取数据.
GetThreadContext(pi.hThread, &Regs) ;

Regs.Dr0
= Regs.Dr7 = 0 ;

ReadProcessMemory( pi.hProcess,(LPVOID)READ_ADDRESS,ReadBuffer,
32,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

 


推荐阅读
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法
    本文介绍了修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法。首先解释了UEFI的概念和作用,然后提供了两种解决方法。第一种方法是在bios界面中将Boot Mode设置为Legacy Support,Boot Priority设置为Legacy First,并关闭UEFI。第二种方法是使用U盘启动盘进入PE系统,运行磁盘分区工具DiskGenius,将硬盘的分区表设置为gpt格式,并留出288MB的内存。最后,通过运行界面输入命令cmd来完成设置。 ... [详细]
  • 本文介绍了在Python中使用zlib模块进行字符串的压缩与解压缩的方法,并探讨了其在内存优化方面的应用。通过压缩存储URL等长字符串,可以大大降低内存消耗,虽然处理时间会增加,但是整体效果显著。同时,给出了参考链接,供进一步学习和应用。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
author-avatar
缅甸环球国际
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有