查看原文
其他

TSG CTF 2020 Reverse-ing

CrackM 看雪学院 2021-03-07

本文为看雪论坛优秀文章

看雪论坛作者ID:CrackM



上周末做了TSG CTF,感觉这个reverse题目还挺有创意,参考了Writeup发现他们有些点没讲出来,我在这里补充一下。

先附上原文链接:https://0x90skids.com/tsg-ctf-writeup/#reverse-ing

Solved By:not-matthias

Points:114

Flag:TSGCTF{S0r3d3m0_b1n4ry_w4_M4wa77e1ru}
 
拿到题目的第一件事就是检查二进制架构,目标操作系统以及是否保留了调试信息。

$ file reversingreversing: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

现在我们知道他是一个Linux的ELF文件,拖到IDA里面看一下_start函数,可以看到他先是跳到了reverse函数里面进行执行,但是执行完Call rbx之后,代码就变成了一团糟:



reverse函数里面对_start函数进行了修改,所以每次我们从call rbx回来之后,代码都发生了变化:



我最开始直接把代码复制过去,然后写了一个python脚本来转换指令,但是实话实说这个有点难而且花了我很多时间。

后面@jeff_提到reverse函数调用了很多次决定采用另一种方法。我从_start函数的起始地址开始,遍历所有的代码,检查是否有jmp rbx的opcode存在。

因为我们知道在跳转之前的代码都是能够正确执行的,所以我们jmp rbx之前的代码保存在输出文件中。接下来我们调用reverse函数,转换_start函数的代码,继续往下执行:

file = open('reversing', 'rb')output = open('reversing_deobfuscated', 'wb')
original = file.read()content = bytearray(original)patched = bytearray(original)
SHELLCODE = 0x1BASTART = 0xE5
JMP_RBX_OPCODE = [0xFF, 0xD3]
def save(from_offset, to_offset): for i in range(from_offset, to_offset): patched[i] = content[i]
def reverse(): # for ( index = 106LL; index >= 0; --index ) # { # opcode = *(shellcode - index); # *(shellcode - index) = *(start + index); # *(start + index) = opcode; # } # for i in range(106, 0, -1): opcode = content[SHELLCODE - i] content[SHELLCODE - i] = content[START + i] content[START + i] = opcode
SAVE_OFFSET = STARTfor IP in range(START, SHELLCODE): # Check if the opcode is `jmp rbx` if content[IP] == JMP_RBX_OPCODE[0] and content[IP + 1] == JMP_RBX_OPCODE[1]: # Save the instructions that have been executed save(SAVE_OFFSET, IP + 2) SAVE_OFFSET = IP + 2
# Patch the `jmp rbx` instructions, since we don't need them anymore. patched[IP] = 0x90 patched[IP + 1] = 0x90
reverse()
# Write to the output file#output.write(patched)

我们用IDA打开已经去混淆的二进制文件,代码已经能够读懂了。但是IDA似乎无法创建函数?即使我们手动创建,也还是会出现错误:


The function has undefined instruction/data at the specified address..



从上到下看了一遍之后,我注意到没有返回状态,所以我把最后一个NOP(0x90)修改为了RET(0xC3)。


之后按P创建函数,F5看伪代码:



那,到了这里大家好像就觉得,“啊,就是个异或和加运算”,这样往下走就行了对不对?并不是!!!

有一点不要忘了,因为reverse函数的存在我们这里面的loc_600194里面的数据,每执行一次reverse函数,都会进行交换。

所以还是要回到汇编代码上来看:

.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.| 48 mov cl, BYTE PTR [rsi+rdx*1] || 53 xor cl, BYTE PTR [rdx+0x600194] || 61 add cl, BYTE PTR [rdx+0x600194] || 69 or rdi, rcx || 74 dec dl || 78 jns 0x600171 <_start+140> ||~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|| 140 mov cl, BYTE PTR [rsi+rdx*1] || 145 xor cl, BYTE PTR [rdx+0x600194] || 153 add cl, BYTE PTR [rdx+0x600194] || 161 or rdi, rcx || 166 sub dl, 0x1 || 171 jns 0x600115 <_start+48> |'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'

先单步来解释一下:

1. 执行48语句,cl = input[0]。


2. 切换上下文,loc_600194=[0x48, 0x80, 0x46, 0xba, 0xa5, 0xd3...],记为A。


3. 执行XOR cl= input[0] ^ 0x48。


4. 切换上下文,loc_600194=[0xE4, 0xD3, 0xFF, 0x05, 0x0F, 0x6B, 0x7C.....],记为B。


5. 执行加法, cl= (input[36] ^ 0xdb + 0xe4)&0xFF。


6. 计算$rdi = $rdi | cl。


7. ......这样循环1-6步,计算直到字符串末尾(计算过程中注意数据切换)。


8. 判断是$rdi是不是0,如果是0,输出字符“correct”,否则输出“wrong”。


因此写出来公式为 Input[i] ^ A[i] + B[i] = 0;i为奇数。

Input[i] ^ B[i] + A[i] = 0;i为偶数。
 
计算Flag的代码为:

X1 = [0x48, 0x80, 0x46, 0xba, 0xa5, 0xd3, 0xff, 0xc0, 0x31, 0x48, 0x1e, 0x65, 0x32, 0xa4, 0x88, 0xd3,0xff, 0xe6, 0x89, 0x48, 0x5f, 0x7a, 0x84, 0x3b, 0xd3, 0xff, 0xd2, 0x31, 0x48, 0x4e, 0x36, 0xc9,0xc5, 0xcf, 0x22, 0x32, 0x58,] X2 = [0xe4, 0xd3, 0xff, 0x05, 0x0f, 0x6b, 0x7c, 0x13, 0xff, 0xca, 0xd3, 0xff, 0xff, 0x31, 0x48, 0x72,0x63, 0x2b, 0x19, 0x8c, 0xd3, 0xff, 0x25, 0xb2, 0x19, 0x5e, 0x61, 0xfb, 0xc1, 0xd3, 0xff, 0x00,0x60, 0x00, 0xb0, 0xbb, 0xdb,] flag = ""for i in range(0x25): if i%2==0: f = (-X2[i]^X1[i])%0x100 else: f = (-X1[i]^X2[i])%0x100 flag += chr(f)print(flag)

最后输出flag:TSGCTF{S0r3d3m0_b1n4ry_w4_M4wa77e1ru}。



- End -

看雪ID:CrackM

https://bbs.pediy.com/user-560717.htm

  *本文由看雪论坛 CrackM 原创,转载请注明来自看雪社区。


推荐文章++++

* ollvm算法还原案例分享

* 以显示b站楼层编号为例,上手油猴脚本与抓包

* 举杯邀Frida,对影成三题

* CVE-2020-0624 win32k漏洞分析笔记

* Galgame汉化中的逆向(三):自定义字库分析


好书推荐












公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



ps. 觉得对你有帮助的话,别忘点分享点赞在看,支持看雪哦~


“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存