危险漫步博客
新鲜的“黑客思维”就是从全新的角度看待黑客技术,从更高的层面去思考;专注于黑客精神及技术交流分享的独立博客。
文章2289 浏览18982160

伪造函数参数逆向分析控制台程序

众所周知,Windows平台的程序可以简单的分为图形界面程序(GUI)和控制台程序(Console),两者的分界线实际上是很模糊的,我们可以借助于/entry和/subsystem两个链接器参数指明其入口的启动函数和运行所需要的子系统环境;相信对于图形界面程序的逆向,朋友们都已经接触过很多了,但是在现实中我们会碰到很多前辈们写的经典的控制台程序,比如mt.exe、nc.exe等等,要更好的使用这些工具、提高编程能力,熟悉这些老牌经典黑客工具的原理是很有必要的,下面,危险漫步将带着大家靠提权机制来熟悉控制台程序程序的逆向步骤。

一,脱壳

用Peid查壳提示什么都没找到,但是EP区段是UPX1,事实证明的确是UPX。OD载人,CTRL+F搜索popad,找到位置,在此按置下断,F9运-j程序,取消断点,直接j mp到OEP,用OD自带的脱壳脚本脱壳。运行Import REC进行修复,然而只有一个C/C++运行时库在里面,显然通过工具自动查找IAT是不可以的。图中显示RVA为29650时,能找到msvcrt.dll,那么此处-定是IAT的值置,只不过IAT未被找全而已,在OD命令窗口输入:dd 429650(加上基址Ox00400000),向上翻页,定位IAT的真实RVA在2943c的位置。在lmport REC中将RVA修改为真实的RVA地址2943c,大小填1000(随便填,只要找全即可),直接单击“获取输入表”。所示,IAT获取成功,修复脱壳程序,正常运行,到这里准备工作完成。

二,伪造参数实现动态跟踪一su参数下的代码

2,1分析函数

用OD载入脱壳修复后的程序,直接F7跟进第一层函数,依次跟进相应的函数,程序总是退出,定位代码在如下位置:

exit()是一个运行时库函数,当参数为O时表示正常退出,有汇编代码可知,程序是正常退出的,而不是异常,那为什么会退出呢?答案很简单,因为mt.exe是-个命令行下的控制台程序,在运行时需要手工输入参数,如果没有参数,则只会显示帮助内容,因此上面在OD中看到的异常,实际上对程序来说是正常的(exit0传递的参数为O)。知道了原因重新载人,手动伪造相应的参数即可。

因为要分析mt -su参数的实现机制,mt -sufilename可以提升filename的权限为system,如果不加filename贝ij将cmd.exe提升为system权限,要理解mt-su的机制,只要知道调用的相关函数及功能即可,因此分jErT/c!有mt -su,提升cmd.exe为System权限的情况即可,主函数参数必须为2,且第二个必须为.su。重新载入,跟进第一层的函数,代码如下:

函数402e28有三个参数,一个是ecx-个是edx一个是eax,这三个寄存器到底是什么东东呢?dd41c004,显示内容为l,这里应该是argc的内容,即参数的个数,dd [edx]。显然是在进程的环境控制块,图中显示的程序名,即为argv[0]指针所指向的内容,因此edx即保存了相关的mt.exe的命令参数,dd ecx,显示内容为系统设置的环境变量,到这里可以搞清楚402e28这个函数的三个参数了,描述如下:

ecx-系统环境变量——进入函数402e28后的地址定位为ebp+Oxl0edx-argv[l-进入函数402e28后的地址定位为ebp+ceax-argc-进入函数402e28后的地址定位为ebp+8

2.2:伪造参数

有上面的分析eax为参数的个数,且最后入栈,因此将当前esp指向的栈空间地址修改为2即可实现mt -su参数个数的伪造。在OD命令栏中输入,dd[edxJ,此时为进程环境控制中的参数列表,我们找到3e2821处,用OD修改内存将参数一su写入,要写入参数,首先将-su转换为十六进制。它对应于Ox2d7375,别忘了这是字符串,因此在末尾要加上一个Ox00,即Ox2d737500,因为Intel的机器为Little endian,因此修改时需要输入Ox0075732d,修改后的内存所示,到这里参数还没伪造完,因为控制台主函数的格式为int main(int argc,char*argv[ll),即argv[]实际上是一个字符指针数组,上面[edx]只是修改了指针所指内存地址的内容,我们还需将-su参数所在的内存地址,保存到argv[l]中才可以,即修改edx+4位置地址为003e2821 (-su参数的内存地址)。修改完这些内容后,即可F7跟进402e28函数了,现在不用再担心程序正常退出了。

三,逆向分析其机制

F7跟进程序后,一路F8狂奔至如下代码处(为了节省版面,删除一些没太多分析意义的指令语句):

由上可知源码框架如下

F4执行到call 40829c处,F7跟进。看见的入口代码,熟悉的SeDebugPrivilege出现了,显然404458处的函数即为令牌修改函数。407FCC是这个程序的最关键call,OD中会提示我们ASSCII码——”inject failed'’,看来程序用的是注入技术,跟进此核心call。

此处有一个函数407ebc,进入后发现是加密cmd.exe /Q,算法很简单,字符串结合数组元素的序号-50x5f(即“)进行xor运算,相当于C++代码中的var“一…;这语句看了是不是很开心,作者加密的原因应该是考虑到了对敏感字符保护,防止将内存中的cmd.exe/Q定位为特征码。

又出来一个手写函数,此处的函数用于枚举系统进程获得serivces.exe系统进程的PID,这是如何得出的呢?首先看函数的参数。

此时栈空间为字符串services,返回值eax的内容为Ox398,我们用hex2dec将十六进制转换成十进制,再查看系统的进程PID-可以知道了。

进入函数你会发现EnumProcess()星pmt.exe是通过EnumProcess0来枚举进程的,而并没有使用TooLhelp系列函数。接下来的东东只要分析程序调用的API函数即可熟悉mt.exe使用的进程注入技术。

线程函数的内容即为memcpy()中的内容,可以在内存中直接反汇编该部分内存的代码。由上面的API调用可知,mt.exe -su的原理就是通过一个系统进程运行一个exe文件,因为系统进程的权限为system,所以它运行的exe文件也是sysiem权限,详细的步骤就是一个非DLL远程进程注入程序,即将线程函数直接写人system权限的进程,从而继承system权限(有关提升system权限的方法,请参考以前危险漫步的博客),具体的步骤如下:

1:通过OpenProcessToken()、LookupPrivilegeValu0、AdjustTokenPrivileges0来获得打开系统进程的权限。

2:通过EnumProcess()枚举系统进程,获取services.exe的进程PID,调用OpenProcess()获得其句柄。

3:通过VirtualAllocEx0在serviees.exe的进程空间中分配内存,然后调用WritProcessMemory0将线程函数写入,再后调用CreateRemoteThread0远程创建线程,最后通过WaitForSingleObject0等待远程线程内核对彖返回。

知道了原理操作起来也就简单了,下面是以注Anotepad.exe为例的直接写线程函数的注入代码。

另外需要注意,其一,上面的代码只是为了演示mt -su参数使用的挂人机制,其二,vista以后因为windows引入了session O隔离的机制,因此以上提升system权限的方法无效。到这里,危险漫步的一次逆向之旅就结束了。