红明谷杯2021:Reverse

红明谷杯2021:Reverse

g0

golang 逆向题

1. flag 长度 : 0x14

1
2
3
4
call    fmt_Fscanf
mov rax, [rsp+0A8h]
mov rcx, [rax]
cmp qword ptr [rax+8], 14h

数据变化 null -> AABBCCDDEEFFGGHHIIJJ

2. Flag 乱序

测试输入:AABBCCDDEEFFGGHHIIJJ
乱序输出:CDDEEHIIJJFFGGHAABBC
还原时,对照位置还原即可。
数据变化: AABBCCDDEEFFGGHHIIJJ -> CDDEEHIIJJFFGGHAABBC

3. 调用 main_Encode 对乱序结果编码

1
2
3
4
.text:00000000004CD3A5 mov     [rsp+0E0h+var_E0], rax ; slice.data
.text:00000000004CD3A9 mov [rsp+0E0h+var_D8], rcx ; slice.len
.text:00000000004CD3AE mov [rsp+0E0h+var_D0], rdx ; slice.cap
.text:00000000004CD3B3 call main_Encode

由调用时参数推断 main_Encode 传入的参数是 []string, 即 golang 的 slice 切片类型。
数据变化: CDDEEHIIJJFFGGHAABBC -> jKbWKuiRNZVR9xFNfdv41ptrx85

4. 比较

1
2
3
.text:00000000004CD58D mov     [rsp+58h+var_50], rcx
.text:00000000004CD592 mov [rsp+58h+var_48], rax
.text:00000000004CD597 call runtime_memequal

数据变化: 2GVdudkYo2CBXoQii7gfpkjTc4gT 与 jKbWKuiRNZVR9xFNfdv41ptrx85 比较

-> 2GVdudkYo2CBXoQii7gfpkjTc4gT 反推输入。

5. main_Encode 流程

5.1 math_big_nat_setBytes

将输入字符串作为大整数(大端序,可以写个go测试)

1
call    math_big_nat_setBytes

x = math_big_nat_setBytes(intputflag)

5.2 循环

循环条件: math_big__ptr_Int_Cmp(x, 0) 即 x > 0 才循环

循环体流程:
调用 math_big__ptr_Int_DivMod

1
func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) 

4个参数,在call math_big__ptr_Int_DivMod 程序点,栈数据如下:
rsp -> z
rsp + 0x8 -> x
rsp + 0x10 -> y
rsp + 0x18 -> m

rsp + 0x20 -> 返回值1: x div y
rsp + 0x28 -> 返回值2: x mod y

z,x,y,m 的类型都是指向 Int 结构体的指针 *Int
Int 结构体定义如下

1
2
3
4
5
type Int struct {
neg bool // sign
abs nat // absolute value of the integer
}
type nat []Word

64位 golang 中 Word 代表的是一个64位整数, nat 就是整数的切片数组。

这些定义对寻找数据很有帮助!

循环代码类似:

1
2
3
4
5
6
x = flag
table = '12Nrst6CDquvG7BefghJKLMEFHPQZabRSTUVmyzno89ApwxWXYcdkij345'
result = ''
while x > 0:
result = result + table[x % 58]
x = x // 58

应该是 base58 编码换表,根据正向过程手写逆向过程如下

1
2
3
4
5
6
7
8
9
target = '2GVdudkYo2CBXoQii7gfpkjTc4gT'
table = '12Nrst6CDquvG7BefghJKLMEFHPQZabRSTUVmyzno89ApwxWXYcdkij345'
c = 0
for i in target:
idx = table.find(i)
c = c * 58
c = c + idx
print(c)
hex(c) ...再转 ASCII

We1CT2345}Fc0m_flag 换顺序得到 flag{We1CTFc0m_2345}

gogogo

TODO…….

参考

[1] “https://golang.org/src/math/big/int.go"
[2] “https://golang.org/src/math/big/nat.go"


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!