ak 了 re,mark 一下
原题链接: 链接:https://pan.baidu.com/s/1lA9Y003K3AhWedge8NuQUw
提取码:1111
easy_re
- 签到题,本身没啥好说的,把几个花指令 nop 掉,就可以 F5 看伪代码
- 可以看到就是一个亦或加密,所以无需关心密钥生成,直接 dump 密钥流即可
- 动调起来后,输入一串 a,让程序运行到比较处时 dump 此时的
fake_cipher
,然后与字符 a 亦或即可得到密钥流cipher = [245, 140, 141, 228, 159, 165, 40, 101, 48, 244, 235, 211, 36, 169, 145, 26, 111, 212, 106, 215, 11, 141, 232, 184, 131, 74, 90, 110, 190, 203, 244, 75, 153, 214, 230, 84, 122, 79, 80, 20, 229, 236] fake_plain = b'a'*len(cipher) print(fake_plain) fake_cipher = [242, 129, 141, 226, 133, 167, 124, 97, 97, 243, 191, 212, 115, 229, 150, 76, 55, 208, 38, 131, 8, 213, 235, 244, 219, 19, 3, 105, 242, 152, 173, 76, 200, 131, 177, 4, 42, 25, 9, 69, 182, 240] keys = [fake_cipher[i] ^ fake_plain[i]for i in range(len(cipher))] flag = '' for i in range(len(cipher)): flag += chr(cipher[i] ^ keys[i]) print(flag)
flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}
babyvxworks
- 一个 VxWork 上的可执行文件,直接拖到 IDA 32 里面就能分析
- 根据交叉引用定位到主函数,发现有不少花指令
-
jz
和jnz
连着用就相当于jmp
了,所以直接把这一大片全部 patch 成nop
即可
- 然后就能查看伪代码了。根据语义可以重命名一下函数
- 关键就在于
enc
函数了,修改一下它的函数原型,改成void
返回值,可以发现就是一个简单的递归
- 由于是单字节加密,所以直接爆破即可
cipher = [188, 10, 187, 193, 213, 134, 127, 10, 201, 185, 81, 78, 136, 10, 130, 185, 49, 141, 10, 253, 201, 199, 127, 185, 17, 78, 185, 232, 141, 87] def brute(): for i in range(len(cipher)): for c in range(0x20, 0x7f): tmp = c for _ in range(30): tmp ^= 0x22 tmp += 3 if tmp & 0xff == cipher[i]: print(chr(c), end='') break brute()
flag{helo_w0rld_W3lcome_70_R3}
抛石机
- 个人认为是很恶心的题…考点完全不在逆向分析而是做一些奇奇怪怪的工作…希望国内比赛这种题可以少一点
- 程序逻辑很简单,基本就是输入一个 uuid,每两个
byte
作为一个十六进制数,然后填充到buffer
里,之后调用函数进行校验
- 然后把
buffer
的数据转换成double
,放到一元二次方程里进行运算 - 随便输入一个 uuid,即可找到 uuid 和
buffer
中填充数据的对应关系,这时就确定了四个double
都是前四个字节是 0,后四个字节是 uuid 中的数据 - 然后就是爆破了…跑了挺久,服了
package main import ( "encoding/binary" "fmt" "math" "runtime" "sync" ) func Float64frombytes(bytes []byte) float64 { bits := binary.LittleEndian.Uint64(bytes) return math.Float64frombits(bits) } func Equation1(src float64) bool { ans := 149.2*src + src*-27.6*src - 129.0 return -0.00003 <= ans && ans <= 0.00003 } func Equation2(src float64) bool { ans := src*-39.6*src + 59.2*src + 37.8 return -0.00003 <= ans && ans <= 0.00003 } func main() { wg := sync.WaitGroup{} var a uint64 runtime.GOMAXPROCS(runtime.NumCPU()) eq1Solves := make([][]byte, 0) eq2Solves := make([][]byte, 0) for a = 0x0; a <= 0xffffffff; a++ { tA := a << 32 f := math.Float64frombits(tA) wg.Add(1) go func() { tmp := make([]byte, 8) if Equation1(f) { binary.LittleEndian.PutUint64(tmp, tA) fmt.Print("1st equation solve: ") fmt.Println(tA) eq1Solves = append(eq1Solves, tmp) } else if Equation2(f) { binary.LittleEndian.PutUint64(tmp, tA) fmt.Print("2nd equation solve: ") fmt.Println(tA) eq2Solves = append(eq2Solves, tmp) } wg.Done() }() } wg.Wait() fmt.Println(eq1Solves) fmt.Println(eq2Solves) }
- 跑出来之后根据题目中的其他限制条件,如大小关系,解出来值的范围可以确定唯一的 flag
flag{454af13f-f84c-1140-1ee4-debf58a4ff3f}