[原创]格式化字符串漏洞执行任意代码分析
首先使用vc++6.0编译一个程序FormatStr.exe,源代码:
_#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[])
{
char buff[1024]; // 设置栈空间
strncpy(buff,argv[1],sizeof(buff)-1);
printf(buff); //触发漏洞
return 0;
}
这里以参数test-%x-%x-%x-%n为例
核心汇编代码MOV DWORD PTR DS:[EAX],ECX,其中寄存器EAX,ECX都可以被用户控制,ECX指前边字符的个数,可以通过调试确定(具体有栈上的数据决定,是零的就排除),EAX指参数“test-%x-%x-%x-%n”的首地址,并且通过添加%x可以使EAX往后移四个地址,可以将任意数据写入任意地址,这样就可以将shellcode的首地址写入函数的返回地址,这样等函数返回时shellcode就可以执行了
%1000x 1000是个十进制数字,表示输出字符串的长度,可以通过这个控制字符串的长度
首先打印栈上的数据:输入“test-%x-%x-%x-%x-%x-%x” 输出:test-12ff04-380e4a-7f-34333231-2d78252d-252d7825 (即栈上的相关信息)

test-%x-%x-%x-%n 调试中断时 EAX=34333231
test-%x-%x-%x-%x-%n 调试中断时 EAX=2d78252d
test-%x-%x-%x-%x-%x-%n 调试中断时 EAX=252d7825
设置immunity debugger为默认调试器
首先观察ECX值的变化,当输入test-%x-%x-%n时,ECX=0x13,即字符串“test-12ff04-380e4a-”的长度19,当输入test-%x-%x-%x-%n时,ECX=0x16,即字符串“test-12ff04-380e4a-7f-”的长度22,当输入test-%x-%x-%x-%x-%n时,ECX=0x1F,即字符串“test-12ff04-380e4a-7f-34333231-”的长度31,所以ECX即前边字符串的长度,但是这个长度是根据栈中具体数值来确定的,所以只能通过调试来确定。
观察EAX的值,当输入test-%x-%x-%n时,EAX=0x7f,即栈中的数值0x7f,当输入test-%x-%x-%x-%n时,EAX=0x74726574,即栈中的0x74726574,当输入test-%x-%x-%x-%x-%n时,EAX=0x2d78252d,即栈中的0x2d78252d,当输入test-%x-%x-%x-%x-%x-%n时,EAX=0x252d7825,即栈中的0x252d7825,可以发现这样的规律,随着%x的增多,EAX的值是栈中以四字节为单位往高地址增长的栈中的数据。
通过以上的介绍,可以看到可以将ECX设置为shellcode的首地址,将EAX设置为函数返回地址所在的栈地址,这样当函数返回时,就会执行shellcode中的代码
首先查找shellcode的首地址,在命令行下运行:FormatStr.exe "test-%x-%x-%x-%n",程序异常自动附加到immunity debugger,

直接在栈中搜索就可以了,可以看到shellcode的起始地址是0x0012FF04,
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
复制成功
