打了两天,第一天出了俩,第二天就出了一个(还不是 Android,只能说非常离谱
ezbyte
看师傅们的 Writeup 都说是 DWARF Expression
, 可以直接用 readelf -wf
就行,我比赛的时候没看出来,直接动态调试分析的。
这里看到把输入压栈,在栈上下内存断点
直接断到虚拟机里了,然后动态调试即可
给出一个非常有限的反汇编器
import ctypes
ins = [0x10, 0xA2, 0xE8, 0x91, 0xD3, 0xF8, 0xDA, 0xE1, 0x85, 0x79,
0x10, 0xFB, 0xDD, 0xEB, 0xDE, 0xBB, 0xF6, 0xEF, 0x9E, 0x1A,
0x10, 0xF8, 0xEE, 0xAC, 0x04,
0x7F, 0x00, # load ?
0x22, # add
0x27, # xor
0x27, # xor
0x10, 0xDC, 0xCF, 0xF0, 0x87, 0xA4, 0xE4, 0xA1, 0x83, 0x22,
0x10, 0xED, 0xC0, 0xE1, 0x8D, 0x92, 0xA8, 0xEC, 0x9F, 0x0F,
0x10, 0xF8, 0xA6, 0x5C,
0x7E, 0x00,
0x22,
0x27,
0x27,
0x10, 0xF1, 0x95, 0xDC, 0xD0, 0xAB, 0x9E, 0x84, 0xFF, 0x75,
0x10, 0xE3, 0x87, 0xDD, 0xD6, 0xF8, 0xB2, 0x8F, 0xE5, 0x10, 0x10, 0xE5, 0xC7, 0xA3, 0x04,
0x7D, 0x00,
0x22,
0x27,
0x27,
0x10, 0xCF, 0xB6, 0x91, 0xCA, 0xB6, 0xBD, 0xEE, 0xA7, 0x24,
0x10, 0xA7, 0x99, 0xA5, 0x80, 0xE5, 0xF1, 0xF7, 0x96, 0x11,
0x10, 0x83, 0xC3, 0x73,
0x7C, 0x00,
0x22,
0x27,
0x27,
0x22,
0x22,
0x22]
def handle_10(ins_buf, offset):
r = ctypes.c_uint64(0)
n = 0
while True:
i = ins_buf[offset]
offset += 1
v = (i & 0x7f) << n
n += 7
r.value |= v
if i & 0x80 == 0:
break
return r.value, offset
i = 0
while i < len(ins):
if ins[i] == 0x10:
i += 1
v, i = handle_10(ins, i)
print(f"push {hex(v)}")
elif 0x70 < ins[i] <= 0x8F:
print(f'load input_part[{ins[i] - 0x7C}]')
i += 2
elif ins[i] == 0x22:
print("push(pop() + pop())")
i += 1
elif ins[i] == 0x27:
print("push(pop() ^ pop())")
i += 1
使用 z3 求解即可
import z3
import struct
flag = [z3.BitVec(f'x_{i}', 64) for i in range(4)]
solver = z3.Solver()
solver.add((flag[3] + 0x8b3778) ^ 0x1a3dbfb3bbdaeefb == 0x790b86d78a647422)
solver.add((flag[2] + 0x171378) ^ 0xf3fb14121b8606d == 0x2206872240fc27dc)
solver.add((flag[1] + 0x88e3e5) ^ 0x10ca3d978ad743e3 == 0x75fe10f2ba170af1)
solver.add((flag[0] + 0x1ce183) ^ 0x112ddf8e50094ca7 == 0x244fb9eb69445b4f)
if solver.check() == z3.sat:
m = solver.model()
flagStr = ''.join(struct.pack("<Q", m[flag[i]].as_long()).decode() for i in range(4))
print('flag{' + flagStr + '3861}')
moveAside
mov 混淆。开始注册了俩异常处理,第一个是调用函数的代码,第二个是就是下面的代码块,在调用函数的异常处理handler下断点,发现是使用 strcmp 逐位对比的 字符串,直接在strcmp 下断点,拉置换表即可。
拉表用的是 IDA Pro 的脚本
from idaapi import *
import time
f = open(r'C:\Users\Sink\Desktop\ctf\a.txt', 'w')
i = 0
while True:
espVal = get_reg_val('esp')
oAddr = get_dword(espVal + 4)
tAddr = get_dword(espVal + 8)
o = get_byte(oAddr)
t = get_byte(tAddr)
if o != t:
patch_byte(oAddr, t)
print(f'{i}: o = {hex(o)}, t = {hex(t)}')
f.write(f'{i}: o = {hex(o)}, t = {hex(t)}\n')
f.flush()
i += 1
continue_process()
time.sleep(1)
if i == 48:
break
wait_for_next_event(WFNE_SUSP, -1)
babyRE
青少年编程,很简单,就不解释了
sercet = [102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73,
0, 86, 4, 87,87, 82, 84, 85, 4, 85, 87, 30]
for i in range(1, len(sercet)):
sercet[i] ^= sercet[i -1]
print(''.join(chr(c) for c in sercet))
ezAndroid
一直觉得是 RCE,到最后结束了我也没想明白,我为啥RCE不了,别人告诉我是目录穿越(出题人,你太卑鄙了,头套必须给你拽掉,狠狠的打你脸
首先,通过文件名、文件大小、没有生成 odex 优化,定位到 cpeweb.apk
, jadx 打开发现有 AndroidX 库,这是个Android 4.4 的系统,肯定就是他了!
先说 RCE,UpgradeWebServer
这里
静默安装,安装后打开,接收器在 SystemUI.apk
不太理解为啥 RCE 不了。
再说,目前成功的做法目录穿越,很明显的路径拼接,可惜我是个逆向,可惜有个更明显的 RCE
flag 存放在根目录,所以 http://47.104.67.173:8000/tmp/img/../../../flag
即可
flutterror
不会!!!!!!
标签:Reverse,solver,0x22,Quals,0x27,0x10,sercet,flag,CISCN2023 From: https://www.cnblogs.com/gaoyucan/p/17440735.html