pwnable_start & ciscn_2019_es_2 & ez_pz_hackover_2016 & pwn2_sctf_2016

  花了两天时间做了这四道题,感觉收获很多。但是这种收获感觉写文章写不出自己的思路,就录制了一个视频。

  pwnable_start

  这道题考察了系统调用,shellcode的编写,和动态调试的知识。

ciscn_2019_es

  这道题考了栈转移,先泄露栈地址,再栈转移回去写rop链。

ez_pz_hackover_2016

  这道题打开学习到的也是动调,发现动态调试真的有用。

pwn2_sctf_2016

  这道题本来不计划放到视频中的,录着录着乱了。。。这里有一个符号判断的问题,感觉视频中没有讲清楚,这里补充一下。

  

   这里是一个v2和32比较大小,v2是等于atoi(&nptr),其实看v2也能看出来,v2是int类型,没有刻意标明是无符号类型,所以在这里就是有符号类型。

  有符号int:-2^31 ~ 2^31-1,即-2147483648 ~ 2147483647。4字节。

  当我们输入-1的时候,实际上的二进制保存的是1111 1111,1111 1111,1111 1111,1111 1111,这里的第一个1其实用来表示正负的。

  所以这里的-1假如转换成无符号的时候大小就是2147483648+2147483647==4294967295

  也就是题目中的这个样子。而我们再看这道题的汇编是怎么写的。

  这里要用cmp指令,我们就先来看一下cmp指令的知识。

cmp(compare)指令进行比较两个操作数的大小
例:cmp oprd1,oprd2
为第一个操作减去第二个操作数,
但不影响第两个操作数的值
它影响flag的CF,ZF,OF,AF,PF
我们怎么判断大小呢?
若执行指令后
ZF=1 这个简单,则说明两个数相等,因为zero为1说明结果为0
当无符号时:
CF=1 则说明了有进位或借位,cmp是进行的减操作,故可以看出为借位,所以,此时oprd1<oprd2
CF=0 则说明了无借位,但此时要注意ZF是否为0,若为0,则说明结果不为0,故此时oprd1>oprd2
当有符号时:
若SF=0,OF=0 则说明了此时的值为正数,没有溢出,可以直观的看出,oprd1>oprd2
若SF=1,OF=0 则说明了此时的值为负数,没有溢出,则为oprd1<oprd2
若SF=0,OF=1 则说明了此时的值为正数,有溢出,可以看出oprd1<oprd2
若SF=1,OF=1则说明了此时的值为负数,有溢出,可以看出oprd1>oprd2
最后两个可以作出这种判断的原因是,溢出的本质问题:
两数同为正,相加,值为负,则说明溢出
两数同为负,相加,值为正,则说明溢出
故有,正正得负则溢出,负负得正则溢出
两数相减,同号,则不溢出;两数为异号,结果与减数符号相同,则溢出。

 偷了张图,感觉更直观了。。。

  上面是直接从百度百科复制过来的,感觉讲的很清楚了。

  所以这道题输入-1的时候,SF=0,OF=1。

  这个时候我们再看jle指令,转移条件寄存器描述是ZF=1 OR SF≠OF。

  在这里,很明显是是要跳转的,所以

  这里就直接跳转过来了,就绕过了这个判断。感觉这里就算是讲清楚了。视频已经在审核中了,等审核完我就把视频扔上来了。真的是感觉学到了好多东西呢。

原文地址:https://www.cnblogs.com/bhxdn/p/12907468.html