Mas0n
to be reverse engineer🐧
翻车鱼

RCTF2021 Rev

师傅们都很强,瑟瑟发抖…肝了3题,一开始觉得很难,但实际上捋清思路后还是很简单的。接触的新知识比较多,不管是龙芯的指令集,还是angr的vex ir,liteos-m内核,都让人眼前一新,未做出的rust,swift逆向都是未曾接触过的领域,可见长路漫漫呐…

LoongArch

龙芯的指令集,找文档

LoongArch-Vol1-EN

LoongArch-Vol1-v1.00-CN.pdf

li.d指令文档里没有…

根据命名规则直接猜这条指令是直接给寄存器赋值

然后根据stack和指令去还原过程,把给的output带进去

给的文件内容是sp+32 ~ sp+96 上的栈内容

写个解密脚本(手残一直没写对

# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: arch1.py
@Time: 2021-09-11 21:43
@Desc: It's all about getting better.
"""

def b2i(b):
    """
    bin to int
    :param b: bin str
    :return: int
    """
    return eval("0b" + b)

def i2b(b):
    """
    int to bin (64 bits)
    :param b: int
    :return: bin str
    """
    return bin(b)[2:].zfill(64)

def ixor(b1, b2):
    return i2b(b1 ^ b2i(b2))

def bitrev(b):
    return b[::-1]

def bitrev8b(b):
    """
    bitrev.8b
    :param b:
    :return:
    """
    return b[0:8][::-1] + \
           b[8:16][::-1] + \
           b[16:24][::-1] + \
           b[24:32][::-1] + \
           b[32:40][::-1] + \
           b[40:48][::-1] + \
           b[48:56][::-1] + \
           b[56:64][::-1]

def bins2bytes(b):
    return int.to_bytes(b2i(b), length=8, byteorder="little")

with open(r"D:\Downloads\Compressed\test\output", "rb") as f:
    stack = f.read()

key1 = stack[:32]
key2 = stack[32:]

xorKey1 = [
    int.from_bytes(key1[0:8], byteorder="little"),
    int.from_bytes(key1[8:16], byteorder="little"),
    int.from_bytes(key1[16:24], byteorder="little"),
    int.from_bytes(key1[24:32], byteorder="little"),
]

xorKey2 = [
    int.from_bytes(key2[0:8], byteorder="little"),
    int.from_bytes(key2[8:16], byteorder="little"),
    int.from_bytes(key2[16:24], byteorder="little"),
    int.from_bytes(key2[24:32], byteorder="little"),
]

ended = '1' * 64

t4 = ixor(xorKey2[0], ended)
t5 = ixor(xorKey2[1], ended)
t6 = ixor(xorKey2[2], ended)
t7 = ixor(xorKey2[3], ended)

print("-------------------------- 1 --------------------------")
print("t4 = \"" + t4 + "\"")
print("t5 = \"" + t5 + "\"")
print("t6 = \"" + t6 + "\"")
print("t7 = \"" + t7 + "\"")
print()

t0 = bitrev8b(t4)
t1 = bitrev8b(t5)
t2 = bitrev8b(t6)
t3 = bitrev8b(t7)

print("-------------------------- 2 --------------------------")
print("t0 = \"" + t0 + "\"")
print("t1 = \"" + t1 + "\"")
print("t2 = \"" + t2 + "\"")
print("t3 = \"" + t3 + "\"")
print()

# t0 = bytepick(t6, t5)
# t1 = bytepick(t4, t7)
# t2 = bytepick(t5, t4)
# t3 = bytepick(t7, t6)

# t6[0:32] = t0[32:64]
# t5[32:64] = t0[0:32]
#
# t4[0:32] = t1[32:64]
# t7[32:64] = t1[0:32]
#
# t5[0:32] = t2[32:64]
# t4[32:64] = t2[0:32]
#
# t7[0:32] = t3[32:64]
# t6[32:64] = t3[0:32]

t4 = t1[40:] + t2[0:40]
t5 = t2[40:] + t0[0:40]
t6 = t0[40:] + t3[0:40]
t7 = t3[40:] + t1[0:40]

print("-------------------------- 3 --------------------------")
print("t4 = \"" + t4 + "\"")
print("t5 = \"" + t5 + "\"")
print("t6 = \"" + t6 + "\"")
print("t7 = \"" + t7 + "\"")
print()

t0 = bitrev(t4)
t1 = bitrev(t5)
t2 = bitrev(t6)
t3 = bitrev(t7)
print("-------------------------- 4 --------------------------")
print("t0 = \"" + t0 + "\"")
print("t1 = \"" + t1 + "\"")
print("t2 = \"" + t2 + "\"")
print("t3 = \"" + t3 + "\"")
print()

t0 = ixor(xorKey1[0], t0)
t1 = ixor(xorKey1[1], t1)
t2 = ixor(xorKey1[2], t2)
t3 = ixor(xorKey1[3], t3)
print("-------------------------- 5 --------------------------")
print("t0 = \"" + t0 + "\"")
print("t1 = \"" + t1 + "\"")
print("t2 = \"" + t2 + "\"")
print("t3 = \"" + t3 + "\"")
print()

print((bins2bytes(t0) + bins2bytes(t1) + bins2bytes(t2) +bins2bytes(t3)).decode())

Hi!Harmony!

liteos内核 riscv32指令

gitee仓库:liteos_m

莫名其妙的题目,ghidra反编译就完事了

https://cdn.shi1011.cn/2021/09/46b194a20e526ad07fc11c8aabb4fd40.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5
# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: test2.py
@Time: 2021-09-11 13:05
@Desc: It's all about getting better.
"""
import struct

uStack72 = 0x4d524148
uStack68 = 0x44594e4f
uStack64 = 0x4d414552
uStack60 = 0x4f505449
uStack56 = 0x42495353
uStack52 = 0x454c
uStack50 = 0

data = struct.pack("<L", uStack72) + struct.pack("<L", uStack68) + struct.pack("<L", uStack64) + struct.pack("<L", uStack60) + struct.pack("<L", uStack56) + struct.pack("<l", uStack52)
print(data)

也可以qemu运行(然并软

quickstart-lite-env-setup

Valgrind

题目给的angr的日志 IR表达式 valgrind

项目仓库:angr/pyvex

5k多行,考虑脚本解析,整理出汇编

找了几篇介绍VEX IR的

https://brubbish.github.io/52443.html

https://bbs.pediy.com/thread-258508.htm

https://bbs.pediy.com/thread-258541.htm

https://zhuanlan.zhihu.com/p/349182248

简单分析了一下这个log

符号执行传入的文本可以跑出来

# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: test3.py
@Time: 2021-09-12 2:50
@Desc: It's all about getting better.
"""
import struct

print(struct.pack("<L", 0x656d3174).decode(), end="")
print(struct.pack("<L", 0x7530795f).decode(), end="")
print(struct.pack("<L", 0x6a6e655f).decode(), end="")
print(struct.pack("<L", 0x775f7930).decode(), end="")

print(struct.pack("<L", 0x31743561).decode(), end="")
print(struct.pack("<L", 0x775f676e).decode(), end="")
print(struct.pack("<L", 0x6e5f3561).decode(), end="")
print(struct.pack("<L", 0x775f746f).decode(), end="")

print(struct.pack("<L", 0x65743561).decode(), end="")
print(struct.pack("<L", 0x0064).decode(), end="")

print("")
print(len("t1me_y0u_enj0y_wa5t1ng_wa5_not_wa5ted"))

在这之后,程序进行加密

加密步骤大致为

0~36下标循环,两种方式加密,题目要求拿出加密后的内容,下面就是刚vex指令写脚本了

line 1-220 初始化栈空间,内存排布

little endian
ebp:
0xffffffa8: 0x00000000

0xffffffac: 0x00000003

0xffffffb4: 0x41
0xffffffb5: 0x42
0xffffffb6: 0x43
0xffffffb7: 0x44
0xffffffb8: 0x45
0xffffffb9: 0x46
0xffffffba: 0x47
0xffffffbb: 0x48
0xffffffbc: 0x49
0xffffffbd: 0x4a
0xffffffbe: 0x4b
0xffffffbf: 0x4c
0xffffffc0: 0x4d
0xffffffc1: 0x4e
0xffffffc2: 0x4f
0xffffffc3: 0x50
0xffffffc4: 0x51
0xffffffc5: 0x52
0xffffffc6: 0x53
0xffffffc7: 0x54
0xffffffc8: 0x55
0xffffffc9: 0x56
0xffffffca: 0x57
0xffffffcb: 0x58
0xffffffcc: 0x59
0xffffffcd: 0x5a

0xffffffce: 0x656d3174
0xffffffd2: 0x7530795f
0xffffffd6: 0x6a6e655f
0xffffffda: 0x775f7930
0xffffffde: 0x31743561
0xffffffe2: 0x775f676e
0xffffffe6: 0x6e5f3561
0xffffffea: 0x775f746f
0xffffffee: 0x65743561
0xfffffff2: 0x0064

直接C跑

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc,char *argv[])
{
    const char maps[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char key[] = "t1me_y0u_enj0y_wa5t1ng_wa5_not_wa5ted";

    int64_t t14;
    int32_t t74, t142, t20, t27, t31, t38, t39, t44;
    for (int i = 0; i <= 0x24; ++i) {
        if (key[i] + 3 <= 0x5a) {
            key[i] += 3;
        } else {
            t74 = (int32_t)key[i] + 3 + 0xffffffa6;
            t14 = (int64_t)t74 * 0x4ec4ec4f;
            t142 = (int32_t)(t14 >> 32);
            t20 = t142 >> 0x03;
            t27 = t74 >> 0x1f;

            t31 = t20 - t27;
            t38 = t31 * 0x0000001a;
            t39 = t74 - t38;
            t44 = t39 - 0x00000001;
            key[i] = maps[t44];
        }
    }
    printf("%s", key);
    return 0;
}
本文链接:https://blog.shi1011.cn/ctf/1601
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可

Mas0n

文章作者

发表回复

textsms
account_circle
email

翻车鱼

RCTF2021 Rev
师傅们都很强,瑟瑟发抖...肝了3题,一开始觉得很难,但实际上捋清思路后还是很简单的。接触的新知识比较多,不管是龙芯的指令集,还是angr的vex ir,liteos-m内核,都让人眼前一新,未做…
扫描二维码继续阅读
2021-09-13