「“其他”」的归档WannaCry勒索软件中,利用了NSA泄露工具中的“永恒之蓝”漏洞,关于这个漏洞,之前已经有一些分析,在我看的文章中,http://blogs.360.cn/360safe/2017/04/17/nsa-eternalblue-smb/说得最详细,该文章中针对win7 32位的系统的漏洞触发过程进行了分析。 但是在整个网络上,我没有看到关于64位系统的分析,因此我在该文章的基础上,对win7 64位的触发,以及触发后的shellcode的行为进行了分析整理成此文。 其中若有疏漏,还请大家指教。最后感谢武汉科锐,感谢钱老师的悉心教学,钱老师严谨的治学作风和渊博的知识深深的影响着我,使我受益终身。
搭建测试环境 因为样本的原有行为,是随机产生IP地址,并对目标进行发包。这非常不方便我们测试。因此,需要先在特定的位置断下,将IP地址改为我们的测试目标,并拍快照记录。 具体步骤如下: 1. 在0x00407982处下断,该处为拼接IP字符串,在此处将该字符串修改为自己的测试目标值。 2. 单步(如果不单步可能会因为多线程的原因造成测试不成功,因此推荐单步)至下方的线程创建函数,并在该线程回调处下断点。 3. 在上一步的线程回调函数中,有两处关键点,一处为该样本的第一波发包攻击,攻击结果为:在远程电脑上安装一个后门;第二处为第二波发包攻击,攻击结果为:利用第一波攻击安装的后门,在远程电脑上的系统进程中注入一个dll。他们的调用位置如下图所示: 漏洞的原理 在Srv.sys中的SrvOs2FeaListToNt函数中,会有以下调用关系: SrvOs2FeaListToNt call SrvOs2FeaListSizeToNt call SrvOs2FeaToNt 其中在SrvOs2FeaListSizeToNt中因为有一个DWORD*转WORD*并赋值的bug,造成在SrvOs2FeaListToNt的一个循环中,SrvOs2FeaToNt被调用的次数会多于预期,而造成SrvOs2FeaToNt中的一个memmove拷贝越界。 可以看到,运行到下图时,对大小为0x11000:
通过!pool指令查看:
而实际运行时: 不过,越界覆盖后,最终pool中的地址+0xa8处的数据,会作为一个指针被当作数据接受缓冲区,这是为什么,这其中的原理我没有完全搞明白,还请熟悉的朋友指教。 定位第一轮发包的shellcode触发点 尝试定位shellcode,要知道一个前提,这在其它报告中也已经提到,那就是 该样本的第一次发包,会安装一个后门,该后门的实现方式是在srv模块中,挂钩SrvTransaction2DispatchTable表中的一个表项,可以通过命令. 我之后就是利用这一点,来检验自己的测试机是否已经被触发漏洞,并一步步定位到触发点的(见下文分析). kd> dps srv!SrvTransaction2DispatchTable查看: 挂钩前: </pre> fffff880`0301e760 fffff880`03088780 srv!SrvSmbOpen2 fffff880`0301e768 fffff880`0304fb20 srv!SrvSmbFindFirst2 fffff880`0301e770 fffff880`03085f40 srv!SrvSmbFindNext2 fffff880`0301e778 fffff880`03051650 srv!SrvSmbQueryFsInformation fffff880`0301e780 fffff880`0307ad20 srv!SrvSmbSetFsInformation fffff880`0301e788 fffff880`0304f670 srv!SrvSmbQueryPathInformation fffff880`0301e790 fffff880`03088cb0 srv!SrvSmbSetPathInformation fffff880`0301e798 fffff880`0304d420 srv!SrvSmbQueryFileInformation fffff880`0301e7a0 fffff880`0304e080 srv!SrvSmbSetFileInformation fffff880`0301e7a8 fffff880`0306f660 srv!SrvSmbFsctl fffff880`0301e7b0 fffff880`03088ae0 srv!SrvSmbIoctl2 fffff880`0301e7b8 fffff880`0306f660 srv!SrvSmbFsctl fffff880`0301e7c0 fffff880`0306f660 srv!SrvSmbFsctl fffff880`0301e7c8 fffff880`0307b4f0 srv!SrvSmbCreateDirectory2 fffff880`0301e7d0 fffff880`0306f460 srv!SrvTransactionNotImplemented fffff880`0301e7d8 fffff880`0306f460 srv!SrvTransactionNotImplemented <pre> 挂钩后: </pre> fffff880`0301e760 fffff880`03088780 srv!SrvSmbOpen2 fffff880`0301e768 fffff880`0304fb20 srv!SrvSmbFindFirst2 fffff880`0301e770 fffff880`03085f40 srv!SrvSmbFindNext2 fffff880`0301e778 fffff880`03051650 srv!SrvSmbQueryFsInformation fffff880`0301e780 fffff880`0307ad20 srv!SrvSmbSetFsInformation fffff880`0301e788 fffff880`0304f670 srv!SrvSmbQueryPathInformation fffff880`0301e790 fffff880`03088cb0 srv!SrvSmbSetPathInformation fffff880`0301e798 fffff880`0304d420 srv!SrvSmbQueryFileInformation fffff880`0301e7a0 fffff880`0304e080 srv!SrvSmbSetFileInformation fffff880`0301e7a8 fffff880`0306f660 srv!SrvSmbFsctl fffff880`0301e7b0 fffff880`03088ae0 srv!SrvSmbIoctl2 fffff880`0301e7b8 fffff880`0306f660 srv!SrvSmbFsctl fffff880`0301e7c0 fffff880`0306f660 srv!SrvSmbFsctl fffff880`0301e7c8 fffff880`0307b4f0 srv!SrvSmbCreateDirectory2 fffff880`0301e7d0 fffff880`053e2060 fffff880`0301e7d8 fffff880`0306f460 srv!SrvTransactionNotImplemented <pre> 可以发现第0xe项会被hook。这个表项的hook是由一段shellcode代码所完成的,具体如何定位到shellcode的入口,见以下分析。
因为已知漏洞会在srvnet! SrvNetWskReceiveComplete中完成触发,只是不确认win 7 64位的shellcode写入点是否与前辈win 7 32位地址一样(通常不一样),因此一开始通过下断点并打印内存情况摸索规律: </pre> kd> u srvnet!SrvNetWskReceiveComplete+0x15: fffff880`02d3cdc5 488bca mov rcx,rdx fffff880`02d3cdc8 498bf8 mov rdi,r8 kd> ba e1 srvnet!SrvNetWskReceiveComplete+0x15 "dq r8 r8+0x48;gc" <pre> 得到以下结果: fffffa80`049236b0 00000000`00000003 fffffa80`042fd800 fffffa80`049236c0 fffffa80`042fd800 000059b4`918947fc fffffa80`049236d0 fffffa80`049237f0 00000000`00000810 fffffa80`049236e0 fffffa80`04923710 fffffa80`00000000 fffffa80`049236f0 00000000`00000438 fffffa80`0568d730 …… fffffa80`04a9b010 00000000`0000ffff 00000000`0000ffff fffffa80`04a9b020 00000000`00000000 00000000`00000000 fffffa80`04a9b030 00000000`ffdff100 ffdff020`00000000 fffffa80`04a9b040 ffffffff`ffdff100 00000000`10040060 fffffa80`04a9b050 00000000`ffdfef80 ffffffff`ffd00010 经过比对,发现以上标红内容特殊,是x86报告所记录的溢出时机断点。因此重启环境,下条件断点: kd> ba e1 srvnet!SrvNetWskReceiveComplete+0x15 ".if(poi(@r8+0x48) == 0xffffffffffd00010){}.else{gc}" 结合以上所知的,SrvTransaction2DispatchTable会被shellcode挂钩,因此在该表项处下断点: kd> ba w8 srv!SrvTransaction2DispatchTable+0x8*0xe 经过验证,在以上第一个断点触发后,继续运行,会触发第二个断点: 但是,当步入ffffffff`ffd00b77后,栈已经被破坏,难以定位到该段shellcode的触发点。
在我所看到的其它的分析文章中,均没有提及具体是个位置转移到shellcode的,因此只有自己定位。
考虑到shellcode一般均需要间接call,因此,通过寻找SrvNetWskReceiveComplete中的间接call,并下断点排查。最终,定位到shellcode触发点srvnet!SrvNetCommonReceiveHandler+0xb7: kd> u srvnet!SrvNetCommonReceiveHandler+0xb3 srvnet!SrvNetCommonReceiveHandler+0xb3: fffff880`028017e3 89742420 mov dword ptr [rsp+20h],esi fffff880`028017e7 41ff5208 call qword ptr [r10+8] fffff880`028017eb 8be8 mov ebp,eax fffff880`028017ed 488b0d1cc90100 mov rcx,qword ptr [fffff880`0281e110] fffff880`028017f4 493bcf cmp rcx,r15 fffff880`028017f7 740b je srvnet!SrvNetCommonReceiveHandler+0xd4 (fffff880`02801804) fffff880`028017f9 0fba612c09 bt dword ptr [rcx+2Ch],9 fffff880`028017fe 0f82be840000 jb srvnet! ?? ::FNODOBFM::`string'+0x1341 (fffff880`02809cc2) 在该处下断点验证: kd> bp srvnet!SrvNetCommonReceiveHandler+0xb7 确实可以截取到shellcode的进入入口: 第一轮shellcode的行为分析 为了测试方便,可以下以下条件断点,这样运行win7测试机器后,断下的地点就是shellcode的入口: ba e1 srvnet!SrvNetWskReceiveComplete+0x15 ".if(poi(@r8+0x48) == 0xffffffffffd00010){bp srvnet!SrvNetCommonReceiveHandler+0xb7;gc}.else{gc}" 进入shellcode后,该样本在进行奇怪的jne和call之后(我认为是防止静态分析以及弄乱栈),修改了第0C0000082h号MSR: </pre> ffffffff`ffd00201 31c0 xor eax,eax ffffffff`ffd00203 4090 xchg eax,eax ffffffff`ffd00205 7408 je ffffffff`ffd0020f ffffffff`ffd0020f e8a7000000 call ffffffff`ffd002bb ffffffff`ffd002bb b9820000c0 mov ecx,0C0000082h ffffffff`ffd002c0 0f32 rdmsr ffffffff`ffd002c2 48bbf80fd0ffffffffff mov rbx,0FFFFFFFFFFD00FF8h ffffffff`ffd002cc 895304 mov dword ptr [rbx+4],edx ffffffff`ffd002cf 8903 mov dword ptr [rbx],eax ffffffff`ffd002d1 488d050a000000 lea rax,[ffffffff`ffd002e2] ffffffff`ffd002d8 4889c2 mov rdx,rax ffffffff`ffd002db 48c1ea20 shr rdx,20h ffffffff`ffd002df 0f30 wrmsr ffffffff`ffd002e1 c3 ret ffffffff`ffd00214 c3 ret srvnet!SrvNetCommonReceiveHandler+0xbb: fffff880`02cec7eb 8be8 mov ebp,eax <pre> 这样,利用系统原有的系统调用,样本有机会时系统运行到其准备好的shellcode(ffffffff`ffd002e2)处,经实测,在该处下断点会系统崩溃,但是在其后1条指令处下断点,则不会崩溃: kd> bp ffffffff`ffd002e5 此处开始的shellcode,会寻找内存中的PE格式、定位PE文件头、定位服务表项的位置,最终将服务表项进行hook,但是代码流程的细节需要亲自调试才能看清楚。在此我就不截图了。
病毒样本的第二轮发包攻击 先在后门处下断点: </pre> kd> dps srv!SrvTransaction2DispatchTable fffff880`03302760 fffff880`0336c780 srv!SrvSmbOpen2 fffff880`03302768 fffff880`03333b20 srv!SrvSmbFindFirst2 fffff880`03302770 fffff880`03369f40 srv!SrvSmbFindNext2 fffff880`03302778 fffff880`03335650 srv!SrvSmbQueryFsInformation fffff880`03302780 fffff880`0335ed20 srv!SrvSmbSetFsInformation fffff880`03302788 fffff880`03333670 srv!SrvSmbQueryPathInformation fffff880`03302790 fffff880`0336ccb0 srv!SrvSmbSetPathInformation fffff880`03302798 fffff880`03331420 srv!SrvSmbQueryFileInformation fffff880`033027a0 fffff880`03332080 srv!SrvSmbSetFileInformation fffff880`033027a8 fffff880`03353660 srv!SrvSmbFsctl fffff880`033027b0 fffff880`0336cae0 srv!SrvSmbIoctl2 fffff880`033027b8 fffff880`03353660 srv!SrvSmbFsctl fffff880`033027c0 fffff880`03353660 srv!SrvSmbFsctl fffff880`033027c8 fffff880`0335f4f0 srv!SrvSmbCreateDirectory2 fffff880`033027d0 fffffa80`040a3060 fffff880`033027d8 fffff880`03353460 srv!SrvTransactionNotImplemented kd> ba e1 fffffa80`040a3060 <pre> 接着,触发第二轮攻击,等待断点触发。以下是行为分析。
shellcode的行为分析 第二轮发送的包,为SMB2协议的包,其timeout项,被作为控制flag。 该域经过计算后,它只有三种值,分别对应了“检查”、“卸载”和“执行程序”,计算公式如下: 域的解析判断部分如下: 在经过ping包后,会执行exec包,执行的程序也包含在(拼接后并解码后的)SMB2包中。其行为为: 1. 找ntoskrnl的基址: 2. 通过hash,找出关键的系统调用 3. 通过遍历PID,获取EPROCESS,在通过比对进程EPROCESS中进程名的HASH值,获取指定的进程PID
最后,利用apc注入,将自带的dll注入到指定系统进程中,apc注入看雪中已有相关文章。 Apc的回调函数地址是: 也就是刚才拷贝的apc注入的shellcode,用于内存加载dll,并执行其唯一的导出函数PlayGame,该shellcode及dll我均已经dump出,大家可以从附件下载: PlayGame运行后,会释放并执行母体,溢出攻击到此结束,但是悲剧将在新的机器上循环上演。 漏洞背景: Samba是在Linux和UNIX系统上实现SMB协议的一个软件,2017年5月24日Samba发布了4.6.4版本,中间修复了一个严重的远程代码执行漏洞,漏洞编号CVE-2017-7494,漏洞影响了Samba 3.5.0 之后到4.6.4/4.5.10/4.4.14中间的所有版本,,确认属于严重漏洞,可以造成远程代码执行。 环境搭建: 靶机环境 : Linux-mint 17 镜像网上随便下内核版本3.13.0-24-generic x86_64 samba版本: 4.1.6-Ubuntu 然后配置smb服务配置 参考其他人分析在末行加入 但是我自己测试 只需要就可以
/etc/init.d/iptables stop 看当前靶机ip 攻击机环境: kali2017-amd64 .iso :https://www.kali.org/downloads/ 直接安装镜像即可,linux kali 自带metasploit框架,利用起来非常的方便 Exploit_CVE-2017-7494(msf-ruby) :https://github.com/hdm/metasploit-framework/blob/0520d7cf76f8e5e654cb60f157772200c1b9e230/modules/exploits/linux/samba/is_known_pipename.rb 在攻击机上扫描目标靶机是否445 端口是否打开,因为samba服务开启需要开启445端口 可以看到445和139端口open开启 把down下来的ruby脚本is_known_pipename.rb拷贝至kali机器上的/usr/share/metasploit-framework/modules/exploits/linux/samba/目录下 启动启动msfconsole,并选择使用is_known_pipename模块: 设置目标机ip等,看下配置选项: 可以看到尝试着在靶机的共享目录下上传一个随机字符串生成的so文件,然后就会回连一个shell,看出ip就是靶机的ip 获取一个组ID为root的shell终端。 漏洞代码分析: 官方给出的漏洞补丁可以看出: 漏洞出现在source3/rpc_server/srv_pipe.c 的475行中也就是发生在is_known_pipename函数中对传进来的管道名称进行了过滤的处理,如果管道名称中含有了“/”的字符进行了过滤,其实更严格的话应该是判断首个字符串是不是‘/’来判断是否需要过滤,后续会有介绍,那么根据补丁来进行分析肯定管道名称带有’/’会触发漏洞,所以跟进代码看一下 再跟: 继续:
可以看出参数pipename参数传递过来就是module_name,如果首字符是’/’的话也就是管道的名称的首字符是’/’也就是传过来的是绝对路径的时候,就会跳到load_module函数中,在跟进去就是会加载上传上来的so,而且导出函数 会以SAMBA_INIT_MODULE的函数名进行导出,然后进行执行导出函数,在代码中搜一下可以 #define SAMBA_INIT_MODULE “samba_init_module” 所以上传的so必须要是以samba_init_module函数名导出才可以加载,(但是后续分析ruby exp上传的so在dlopen的时候就会结束,但是会得到反弹shell不知道为什么) 动态gdb跟踪调试: 下载 samba-4.5.9.tar.gz 链接:https://download.samba.org/pub/samba/stable/samba-4.5.9.tar.gz 安装好对应的依赖,进行编译,因为本机的smbd服务正在运行,要首先stop系统对应的smbd的服务,然后在调试debug的smbd进程 关掉本机的smbd服务 然后进行调试debug版的smbd程序,在源码目录中的bin中smbd,以交互模式和设置配置文件路径进行启动 在exp set SMB_SHARE_BASE /tmp 靶机这gdb 跟进:
打印module名称就是从攻击机上上传上来的恶意的so的名称,然后进入到load_module函数中: 然后通过do_smb_load_module->load_module函数中,最后在load_module中加载so,并且导出函数并且执行下图为加载上传的so文件: 然后加载执行,但是这个恶意的so中无论是gdb调试还是正常的运行中都会在dlopen之后退出,然后回弹一个远程shell,不再执行导出函数和执行函数的步骤,这块还不懂怎么回事,希望厉害的人可以解答一下,so就在附件中。 临时解决方案: 在samba的配置文件global节点中添加nt pipe support = 0,即关闭pipe支持(依赖pipe的功能受影响),然后重启服务。 参考链接: http://www.4hou.com/technology/4983.html http://bobao.360.cn/learning/detail/3900.html http://bobao.360.cn/news/detail/4180.html https://github.com/omri9741/cve-2017-7494 https://wiki.samba.org/index.php/Build_Samba_from_Source https://github.com/samba-team/samba/commit/04a3ba4dbcc4be0ffc706ccc0b586d151d360015
很早就听闻Ghost的大名,界面简洁,响应速度极快,同时支持多人管理,一直以来没想着把玩,这次记起来就做了这个教程,如有纰漏,欢迎指正。 什么是Ghost?Ghost 是一套基于 Node.js 构建的开源博客平台(Open source blogging platform), Linux下Node.js的安装下载最新的nodejs,这里强烈推荐下载官方已编译好的版本,自行编译比较麻烦,而且容易遇到各种诡异的问题。 wget https://nodejs.org/dist/v5.3.0/node-v5.3.0-linux-x86.tar.gz 下载后解压 tar -xzvf node-v5.3.0-linux-x86.tar.gz 解压后将文件夹放到你认为合适的地方 关联全局 ln -s /home/jt4b/node-v5.3.0-linux-x86/bin/node /usr/local/bin/node ln -s /home/jt4b/node-v5.3.0-linux-x86/bin/npm /usr/local/bin/npm ln -s /home/jt4b/node-v5.3.0-linux-x86/bin/n /usr/local/bin/n 这样你就直接能在控制台输入指令了 node -v npm -v 查看版本 安装成功 Ghost的安装以及遇到问题这里下载的是Ghostchina制作的Ghost 0.7.4中文集成版 wget http://dl.ghostchina.com/Ghost-0.7.4-zh-full.zip unzip -uo Ghost-0.7.4-zh-full.zip 解压后进入目录,执行 npm install --production 这时居然报错了,运行npm start看看,可以看到 看来是Ghost并不支持最新版本的node,怎么办呢?还好node附带一个非常方便的管理模块n n 0.10.28 就可以轻松切换到0.10.28版了 (推荐用0.10.21) 此时再执行 npm install --production 就安装成功了。 database: { client: 'mysql', connection: { host : '127.0.0.1', user : 'test', password : 'test', database : 'ghost', charset : 'utf8' }, debug: false } 开启的端口可以自行设置config.js找到如图位置修改 npm start 可以看到顺利启动了,浏览器输入 http://ip:5555 已经能顺利访问。 但这还不行,因为当你结束会话时,任务就会结束。所以此时就要用到forver了 npm install forever -g 安装forver CD进Ghost目录 NODE_ENV=production forever start index.js 这时Ghost就挂载到forver上了,如果想关闭可以通过 forever stop PID 指令进行。 Nginx反向代理设置这时已经可以通过IP:5555访问我们的Ghost了,可这样并不便捷也不美观,这里我要将其绑定到我的二级域名ghost.jt4b.com上 vi /usr/local/nginx/conf/nginx.conf 将下列代码添加进去 server { listen 80; server_name ghost.jt4b.com; location ~ { proxy_pass http://ip:5555; //自行修改 } access_log /home/wwwroot/jt4b.com/log/ghost.log combined; #access_log end error_log /home/wwwroot/jt4b.com/log/ghost.log crit; #error_log end } 这里我启用了日志,不想启用可以改成 access_log off; #access_log end error_log /dev/null; #error_log end 保存后 nginx -s reload 重启nginx 来知乎混了一段时间,对于这个人数不算少的群体产生了点儿疑问。 1.对于大多数人来说,就算身边有一个极端爱国的人士,恐怕也会感觉“这人有点儿奇怪”,对于老百姓来说,政治本来就不是生活的主要部分,更遑论极端地爱着日本国了=_=。另,据我出国留学的姐姐说,外国人比中国人更不关心政治。 那么问题来了,在中国的土壤上,中国的百姓群体中,怎么会出现这种极端关心政治的“精神外国人”?这是我第一个不太理解的地方。 2.据我的不完全观察和统计,精日群体普遍对我国政府,甚至是我民族有一种敌视,甚至仇视的态度。不知这是不是我的错觉,如果不是,那么问题来了。 我不知道日本的道德标准怎样,但窃以为“君子绝交不出恶言”无论在哪都是种美德,就算由于一些原因敌视中国政府可以理解,但对于我国人民的敌视就让人有些困惑了,想出国没什么不可以,窃以为想改国籍也属于个人选择,但没必要做到这样吧?那些整天嘴边挂着“贵国,贵民族”的人是什么心态?这是我第二个不理解的地方。 3.就算由于政治原因厌恶我国政府,向往民主,那美国应该更合适啊,无论国力还是体制,美国都比日本要优秀,就算不哈美,世界上大把大把的民主发达国家,为何没有像“精日”一样形成一个有一定规模的群体呢?这是我第三个不了解的地方。 另外,我无意挑衅日本人民(或者说不是主要目的),只是单纯地对这个问题有些好奇,希望有人能帮我解答。 著作权归作者所有。 有些答案真是揣着明白装糊涂啊。精日和普通的对日文化or二次元爱好者,你当别人看不出吗?我在知乎也关注了结识了几个在日留学的大V,他们对日本文化和生活中优秀的部分自然肯定,但对其中不足也不否认。既不需要对日本美化,也无需靠贬低中国替日本抬高身价。我怎么没见有人说他们都是精日?呵呵,你们自己装鸵鸟,就说别人是树靶子,你眼拙也当别人不知道你是什么生物么?我来告诉你,为什么会有人被称为精日:有些人,谈及南京大屠杀,基本就是日本右翼的说辞,甚至有过之而无不及,仿佛侵略屠城是天然正义;中国似乎死的有点少了嘛;加强版可以见精神坂大留学生关于天津爆炸的微博奇葩言论。作为二战战败国,国际秩序所要打压的对象,日本的旧天皇体制是绝对受到批判的;而在某些生物眼里,宛若维新志士一样,似要山呼天皇万岁;喜爱日本优越发达的生活条件,我权且当你是嫌贫爱富也罢,单纯追求个人生活惬意也罢,都无可厚非。但是从简单的物质条件直接“升华”到人性,从而强行批判乃至发泄仇恨一般攻击中国,你们的想象力是如此的跃进迅速,你们的逻辑是如此跳跃和令人赞叹;把一个战败国的突破现国际秩序行为拔高到无以复加,你难道不觉得你在打你美国爸爸的脸么?美帝的原子弹是白放的咯?当天上的流星么?嗯,我到的确挺希望那里来一场“流星雨”的。不要装了,你以为别人都是傻子么。普通的个人出于生活和兴趣的喜好,和你们上升至民族,国家,乃至人种的“喜好”,能一样么。至于精日典型,知乎上多了去了。有山西某大学梦中留学坂大的“精神留学生”,有以自称洗地专业人士的护照爱好者;也有没去过日本就认日本作精神故土的“前世盛唐日本人”。更好笑的是,某些中国很有良心的“国际主义反法西斯”战士的对日态度,仿佛几十年前战败国和法西斯肇乱者是中国一样,中国纪念反法西斯都可以伤及他们精神母国的情感。我说,连日本人也不好意思颠倒法西斯对战两方吧。你们不是洗地,你们简直就是在给日本整容换皮。防卫省怎么没把你们招募进去呢。嘛,不过也是,发了这么多帖子,连归化都没成功(去没去过日本我就更不知道啦哈哈),何谈入防卫省效力呢?多说一句,知乎可以算得上是在华对日态度最亲善的社区了。(此处内容被知乎官方认定不友善hhhh,看过的网友可以在评论区贴出~你跟我说大家都是看走眼了?是啊,我的确是看走眼了。你说这好好的人不做,为嘛要去做**呢。 其实这是09年的东西了,比较简单的变形壳,是我当时申请LCG时的考题。最近无意中被我从邮箱内翻出来了,同时又联想到最近fly兄的unpack论坛永久关闭的消息,权当对逝去青春的祭奠了。 考题 脱文 004C5C0D 55 push ebp 004C5C11 8BEC mov ebp, esp 004C5C16 83C4 F0 add esp, -10 004C5C1C B8 D8D44900 mov eax, 0049D4D8 004C5C24 E8 8305F4FF call 004061AC 004C5C29 A1 DCF44900 mov eax, dword ptr [49F4DC] 004C5C31 8B00 mov eax, dword ptr [eax] 004C5C36 E8 5529F9FF call 00458590 jmp 0049D7F4 //跳向的是FOEP 我比较懒选择后者 修复后DUMP下来 首先OD加载 停在 004C5087 > 60 pushad ; 前几句就有花 但是总体看上去是PESPIN 先设置 除了Invalid or privileged instruction之外其他全选 004C5A4D 85C0 test eax, eax ; kernel32.7C800000 004C5A4F 0F84 28060000 je 004C607D 004C5A55 50 push eax 004C5A56 E8 C5FCFFFF call 004C5720 004C5A5B 2BD2 sub edx, edx 004C5A5D F9 stc 004C5A4D 处停下 向下到 004C5AA6 处F4 CTRL+F9 到达 004C579E 60 pushad 004C579F 0BFF or edi, edi 004C57A1 75 16 jnz short 004C57B9 004C57A3 8B9D D9224000 mov ebx, dword ptr [ebp+4022D9] 004C57A9 2D 01000000 sub eax, 1 004C57AE 8B0483 mov eax, dword ptr [ebx+eax*4] 004C57B1 0385 D1224000 add eax, dword ptr [ebp+4022D1] 004C57B7 EB 72 jmp short 004C582B 004C57B9 8B9D D5224000 mov ebx, dword ptr [ebp+4022D5] 004C57BF 8A47 FF mov al, byte ptr [edi-1] 004C57C2 24 7F and al, 7F 004C57C4 8885 2B234000 mov byte ptr [ebp+40232B], al 004C57CA FF37 push dword ptr [edi] 004C57CC 8F85 34234000 pop dword ptr [ebp+402334] 004C57D2 2BC9 sub ecx, ecx 004C57D4 80BD E5264000 C>cmp byte ptr [ebp+4026E5], 0CC 004C57DB 75 05 jnz short 004C57E2 004C57DD 74 01 je short 004C57E0 004C57DF 68 8BEC8B3B push 3B8BEC8B 004C57E4 03BD D1224000 add edi, dword ptr [ebp+4022D1] 花指令有点多 清理下后就清楚多了 004C5833 /76 35 jbe short 004C586A 004C5835 |03BD C9224000 add edi, dword ptr [ebp+4022C9] 004C583B |3BF8 cmp edi, eax 004C583D |76 2B jbe short 004C586A 改为 004C5833 /EB 35 jmp short 004C586A 004C5835 |03BD C9224000 add edi, dword ptr [ebp+4022C9] 004C583B |3BF8 cmp edi, eax 004C583D |EB 2B jmp short 004C586A 向下 004C5877 C3 retn 处F4 继续向下看 004C5B20 FF6424 FC jmp dword ptr [esp-4] 这里壳开始猥琐IAT了 住手 – -||! jmp 004C5B73 004C5B73 8902 mov dword ptr [edx], eax 这样就跳过了IAT加密 拿IMREC dump下地址就填004C5C0D 抓取后发现指针全为真 注:因为是以前的东西,win7以上系统可能会存在兼容问题 标 题: 【原创】VEH-硬件断点+dll劫持内存补丁 学习加密三内存补丁一节时做的。高手莫要见笑. 下面是用了加密三中的CrackMeNet.exe做的示范. 代码: //设置硬件断点函数 void SetHwBreakpoint() { //添加VEH 参数1=1表示插入Veh链的头部,=0表示插入到VEH链的尾部 AddVectoredExceptionHandler(1, VectoredHandler); //寄存器相关的结构体 CONTEXT _ConText = {CONTEXT_DEBUG_REGISTERS}; //得到当前线程 HANDLE hThread = GetCurrentThread(); // 得到指定线程的环境(上下文) GetThreadContext(hThread, &_ConText); //给调试寄存器值 if (0X0 == _ConText.Dr0 && 0X0 == _ConText.Dr1 && 0X0 == _ConText.Dr2) { _ConText.Dr0 = 0X00401489; _ConText.Dr1 = 0X0; _ConText.Dr2 = 0X0; _ConText.Dr3 = 0x0; _ConText.Dr7 = 0x405; // 设置线程的环境(上下文) SetThreadContext(hThread, &_ConText); } if (0X0 != _ConText.Dr0 || 0X0 != _ConText.Dr1 || 0X0 != _ConText.Dr2 || 0X0 != _ConText.Dr3) { MessageBox(NULL,"设置硬件断点成功..", "(^_^)", MB_OK); } else { MessageBox(NULL,"设置失败,", "提示", MB_OK); } } 代码: // VEH回调函数 LONG WINAPI VectoredHandler( PEXCEPTION_POINTERS ExceptionInfo ) { //判断是否为我们设置的异常地址 if(ExceptionInfo->ExceptionRecord->ExceptionAddress == (PVOID)0X00401489) { MessageBox(NULL, "成功触发异常", "(^_^)", MB_ICONINFORMATION); // 修改当前异常中断的EIP ExceptionInfo->ContextRecord->Eip = 0x00401721;//指向要执行代码的内存地址 // 处理异常. return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH; } 代码: ALCDECL MemCode_connect(void) { SetHwBreakpoint();//调用设置硬件断点 GetAddress("connect"); __asm JMP EAX; } 代码: 00401474 |. 6A 10 push 10 ; /AddrLen = 10 (16.) 00401476 |. 8D85 B0FDFFFF lea eax,[local.148] ; | 0040147C |. 50 push eax ; |pSockAddr 0040147D |. 8B8D 00FEFFFF mov ecx,[local.128] ; | 00401483 |. 51 push ecx ; |Socket 00401484 |. E8 43050000 call <jmp.&WS2_32.#4> ; \connect 00401489 |. 8985 04FEFFFF mov [local.127],eax ; --设置异常地址 0040148F |. 83BD 04FEFFFF>cmp [local.127],-1 代码: 00401721 |. 8BF4 mov esi,esp ; ---异常发生后直接跳到这里执行. 00401723 |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL 00401725 |. 68 887A4100 push CrackMeN.00417A88 ; |Title = "Crackne net-2" 0040172A |. 68 987A4100 push CrackMeN.00417A98 ; |Text = "Registration successful !" 0040172F |. 8B15 90B14100 mov edx,dword ptr ds:[41B190] ; | 00401735 |. 52 push edx ; |hOwner => 001D016C ('Pediy - Crackme (net) 20061204',class='myWindowClass') 00401736 |. FF15 D0D34100 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
在08年初有想过剑走偏锋,利用类似debug api的方法来规避部分游戏检测机制,事实证明和之后的一些人想到一块去了。 |