starctf re 1wp
官方wp:https://github.com/sixstars/starctf2022
simple FILE system
运行一下简单分析
其中plantflag_func 根据a3进行运算 如果是1调用一个解密算法 另一个返回随机 猜测a3是判断flag的标志
用动态调试拿一下v4的值
即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
主体逻辑相当简单
但是跟进到sub_8080900后发现没有call 全用jmp作为跳转
可以看到很多jmp的反跳 反跳的代码无法在F5中显示
这代表IDA错误的将上方的函数识别为函数块
函数块
在由 Microsoft Visual C++ 编译器生成的代码中,经常可以找到函数块
编译器移动不常执行的代码段,用以将经常执行的代码段“挤入”不大可能被换出的内存页,由此便产生了函数块
如果一个函数以这种方式被分割,IDA 会通过跟踪指向每个块的跳转,尝试定位所有相关的块
多数情况下,IDA 都能找到所有这些块,并在函数的头部列出每一个块
有时候,IDA 可能无法确定与函数关联的每一个块,或者函数可能被错误地识别成函数块,而非函数本身
在这种情况下,需要创建自己的函数块,或删除现有的函数块
在反汇编代码清单中,函数块就叫做函数块;在 IDA 的菜单系统中,函数块叫做函数尾(function tail)
要删除现有的函数块,将光标放在要删除的块中的任何一行上,然后选择 Edit -> Functions -> Remove Function Tail
(但我们可以在载入文件时取消勾选 Create function tails 选项 并手动p来创建函数 此步不必须)
分析得知 程序将r15当作rsp使用
这四行完全等价于call 所以patch掉所有相同形式的
重新打开ida 分析
sub_8080100是个TEA
其中720函数是个简单运算 异或的v5+32是定值 所以动态调试拿出来 sub_80800C0 是rol4
#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))