Loading

starctf re 1wp

官方wp:https://github.com/sixstars/starctf2022

simple FILE system

运行一下简单分析

image-20220427223453890

其中plantflag_func 根据a3进行运算 如果是1调用一个解密算法 另一个返回随机 猜测a3是判断flag的标志

image-20220427223641045

image-20220427223938643

用动态调试拿一下v4的值

image-20220430123728698

即rdx DEEDBEEF

写脚本解密即可

def ROR(i, index):
    tmp = bin(i)[2:].rjust(8, "0")
    for _ in range(index):
        tmp = tmp[-1] + tmp[:-1]
    return int(tmp, 2)
def ROL(i, index):
    tmp = bin(i)[2:].rjust(8, "0")
    for _ in range(index):
        tmp = tmp[1:] + tmp[0]
    return int(tmp, 2)

with open(f"image.flag", "rb") as f:
    t = f.read()
f = ""
v4 = 0xDEEDBEEF
for x in t:
    x = ROL(x, 5) | ROR(x, 3)
    x = x & 0xff
    x ^= 0xde
    x = ROL(x, 4) | ROR(x, 4)
    x ^= 0xED
    x = x & 0xff
    x = ROL(x, 3) | ROR(x, 5)
    x ^= 0XBE
    x = x & 0xff
    x = ROL(x, 2) | ROR(x, 6)
    x = (x ^ v4)
    x = x & 0xff
    x = ROL(x, 1) | ROR(x, 7)
    f += chr(x)
t = f.index("CTF")
print(f[t:t + 50])

nacl

image-20220430131738797

主体逻辑相当简单

但是跟进到sub_8080900后发现没有call 全用jmp作为跳转

image-20220430131854243

image-20220430131900414

可以看到很多jmp的反跳 反跳的代码无法在F5中显示

这代表IDA错误的将上方的函数识别为函数块

函数块
在由 Microsoft Visual C++ 编译器生成的代码中,经常可以找到函数块

编译器移动不常执行的代码段,用以将经常执行的代码段“挤入”不大可能被换出的内存页,由此便产生了函数块

如果一个函数以这种方式被分割,IDA 会通过跟踪指向每个块的跳转,尝试定位所有相关的块

多数情况下,IDA 都能找到所有这些块,并在函数的头部列出每一个块

有时候,IDA 可能无法确定与函数关联的每一个块,或者函数可能被错误地识别成函数块,而非函数本身

在这种情况下,需要创建自己的函数块,或删除现有的函数块

在反汇编代码清单中,函数块就叫做函数块;在 IDA 的菜单系统中,函数块叫做函数尾(function tail)

要删除现有的函数块,将光标放在要删除的块中的任何一行上,然后选择 Edit -> Functions -> Remove Function Tail

(但我们可以在载入文件时取消勾选 Create function tails 选项 并手动p来创建函数 此步不必须)

分析得知 程序将r15当作rsp使用

image-20220430171604491

这四行完全等价于call 所以patch掉所有相同形式的

重新打开ida 分析

image-20220430172734313

sub_8080100是个TEA

image-20220430174151893

其中720函数是个简单运算 异或的v5+32是定值 所以动态调试拿出来 sub_80800C0 是rol4

image-20220430173137358

#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
uint32_t map[32] = {
    0x3020100,
    0x1B3C5D7E,
    0x1B3C5D7E,
    0x276AADF0,
    0x2366A9EC,
    0x3FA50A6E,
    0x3BA1066A,
    0x4BD35AE0,
    0x43CB52D8,
    0x53FDA74E,
    0x5C05AF56,
    0x703C07D0,
    0x642FFBC4,
    0x7866543E,
    0x7C6A5842,
    0x8494A4B0,
    0x8494A4B0,
    0xA0D30532,
    0x9CCF012E,
    0xA8FD51A0,
    0xA4F94D9C,
    0xB52BA212,
    0xBD33AA1A,
    0xCD65FE90,
    0xC55DF688,
    0x0D9944F02,
    0x0DD985306,
    0xF1CEAB80,
    0xE5C29F74,
    0xFDFCFBF2,
    0xFDFCFBF2,
    0x6274860,
};
void XTEA_encipher(unsigned int num_rounds, uint32_t v[2], uint32_t key[4])
{
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x10325476;
    int index = 0;
    for (i = 0; i < num_rounds; ++i)
    {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ map[index];
        index++;
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ map[index];
        index++;
    }
    v[0] = v0;
    v[1] = v1;
}
void XTEA_decipher(unsigned int num_rounds, uint32_t v[2], uint32_t *key)
{
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], delta = 0x10325476, sum = delta * num_rounds;
    int index = 0;
    for (i = 0; i < num_rounds; ++i)
    {
        index++;
        index++;
    }

    for (i = 0; i < num_rounds; ++i)
    {
        index--;
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ map[index];

        sum -= delta;
        index--;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ map[index];
    }
    v[0] = v0;
    v[1] = v1;
}

int main()
{

    uint32_t enc32[8] = {

        0xFDF5C266, 0x7A328286, 0xCE944004, 0x5DE08ADC, 0xA6E4BD0A, 0x16CAADDC, 0x13CD6F0C, 0x1A75D936};
    uint32_t t1[2] = {
        0xFDF5C266,
        0x7A328286,
    };
    uint32_t t2[2] = {
        0xCE944004,
        0x5DE08ADC,
    };
    uint32_t t3[2] = {
        0xA6E4BD0A,
        0x16CAADDC,
    };
    uint32_t t4[2] = {0x13CD6F0C, 0x1A75D936};
    uint32_t k[4] = {0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c};
    // XTEA_encipher(1 << (0 + 1), t1, k);
    XTEA_decipher(1 << (0 + 1), t1, k);
    XTEA_decipher(1 << (1 + 1), t2, k);
    XTEA_decipher(1 << (2 + 1), t3, k);
    XTEA_decipher(1 << (3 + 1), t4, k);
    printf("0x%x,0x%x,\n", t1[0], t1[1]);
    printf("0x%x,0x%x,\n", t2[0], t2[1]);
    printf("0x%x,0x%x,\n", t3[0], t3[1]);
    printf("0x%x,0x%x,\n", t4[0], t4[1]);
    system("pause");
}
def ror(i, index):
    tmp = bin(i)[2:].rjust(32, "0")
    for _ in range(index):  # 模拟循环右移
        tmp = tmp[-1] + tmp[:-1]  # 取最后一位 取从第1位到最后一位前一位,拼接起来。相当于右移了一位。
    return int(tmp, 2)


def rol(i, index):
    tmp = bin(i)[2:].rjust(32, "0")
    for _ in range(index):
        tmp = tmp[1:] + tmp[0]
    return int(tmp, 2)


table2 = [0x04050607, 0x00010203, 0x0C0D0E0F, 0x08090A0B, 0xCD3FE81B, 0xD7C45477, 0x9F3E9236, 0x0107F187,
          0xF993CB81, 0xBF74166C, 0xDA198427, 0x1A05ABFF, 0x9307E5E4, 0xCB8B0E45, 0x306DF7F5, 0xAD300197,
          0xAA86B056, 0x449263BA, 0x3FA4401B, 0x1E41F917, 0xC6CB1E7D, 0x18EB0D7A, 0xD4EC4800, 0xB486F92B,
          0x8737F9F3, 0x765E3D25, 0xDB3D3537, 0xEE44552B, 0x11D0C94C, 0x9B605BCB, 0x903B98B3, 0x24C2EEA3,
          0x896E10A2, 0x2247F0C0, 0xB84E5CAA, 0x8D2C04F0, 0x3BC7842C, 0x1A50D606, 0x49A1917C, 0x7E1CB50C,
          0xFC27B826, 0x5FDDDFBC, 0xDE0FC404, 0xB2B30907]


def solvee(v):
    i = 43
    while (i >= 0):
        t = v[0]
        v6 = rol(t, 1)
        v7 = rol(t, 8) & v6
        v8 = v7 ^ rol(t, 2)
        v[0] = v[1] ^ table2[i] ^ v8
        v[1] = t
        i -= 1
    return [v[1], v[0]]
if __name__ == '__main__':
    # print(len(table2))
    # print(hex(0x1B3C5D7E - 0x3020100))
    # print(hex(0x276AADF0 - 0x1B3C5D7E))

    v = [0xe71f5179, 0xb55f9204,
         0x722d4a3a, 0x238e8b65,
         0x4385e0f2, 0x6703757a,
         0xaabe9be3, 0x4de4253b, ]
    for i in range(0, len(v), 2):
        v[i], v[i + 1] = solvee([v[i], v[i + 1]])
    for x in v:
        print(hex(x))

posted @ 2022-04-30 18:39  FW_ltlly  阅读(197)  评论(1编辑  收藏  举报