#逆向-DASCTF2024-复现|寒夜破晓,冬至终章 (完结)
👻5ea1
题目:TreRe
把题目文件直接拖到ida里面,打开main函数,开头直接给了一串数据,赋值给了v21,跟踪v21,可以确定这是最终比较的密文
借助v21是密文这一信息,就能知道v8中存放的是要加密的明文,于是跟踪v8
发现大致分为上下两块,首先分析下块,由v8=v9
知这两者等价,所以后面对v9的操作相当于对v8操作,故下块加密逻辑为逐位异或2
再分析上段,由于此时可以先写出半段exp,故作如下操作
s="M@ASL3MF`uL3ICT2IhUgKSD2IeDsICH7Hd26HhQgKSQhNCX7TVL3UFMeHi2?"
enc=""
for i in s:
enc+=str(chr(ord(i)^2))
print(enc)
得到中间结果OBCQN1ODbwN1KAV0KjWeIQF0KgFqKAJ5Jf04JjSeIQSjLAZ5VTN1WDOgJk0=
,此时结合上段内容,直接猜测是base编码,查看可疑变量中的数据,果然是一个base64的换盒
直接在赛博厨子中解密得到flag
验证flag正确
题目:刻板印象Re
Babyenc?那不得秒了!。。吗?
观察main函数,发现整体逻辑清晰,输入一个长度为48的字符串,然后对它进行一个加密,再和预定义的密文进行一个比较
开始获取信息,信息很完备啊,打开就是,看来能秒
密文能直接看
加密逻辑直接写出来的,就是一个简单异或
异或内容能看,是一句话 Laughter_is_poison_to_fear
,笑死,秒了还会fear吗?
信息齐全,把数据dump下来,直接写脚本开梭
#include<stdio.h>
int main()
{
char s[]="Laughter_is_poison_to_fear";
unsigned char enc[]
{
0x18, 0x09, 0x1C, 0x14, 0x37, 0x1D, 0x16, 0x2D, 0x3C, 0x05,
0x16, 0x3E, 0x02, 0x03, 0x10, 0x2C, 0x0E, 0x31, 0x39, 0x15,
0x04, 0x3A, 0x39, 0x03, 0x0D, 0x13, 0x2B, 0x3E, 0x06, 0x08,
0x37, 0x00, 0x17, 0x0B, 0x00, 0x1D, 0x1C, 0x00, 0x16, 0x06,
0x07, 0x17, 0x30, 0x03, 0x30, 0x06, 0x0A, 0x71
};
int i;
for(i=0;i<=47;i++)
{
enc[i]^=s[i%26];
}
printf("%s",enc);
return 0;
}
梭出来一个fake flag,This_is_clearly_a_fake_flag_so_try_to_find_more.Laughter_is_poison_to_fear
😟
不对不对,啊对的对的,观察汇编发现加密函数里有一段爆红的花指令,没有被展现出来😼ezez,看来要拿下了
选择把一系列E8跳转nop掉,解决花指令
此时再按F5反汇编,可以看到加密部分多了一块tea加密,看来出题人的诡计已经被我们勘破了
简单观察该处tea加密,key处由sum的结果控制下标,然后一轮加密前后两位,是xtea加密算法,直接换盒套个模板梭掉
然后xtea的密钥即v8直接给出了
unsigned int *k=(unsigned int *)enc;
unsigned int delta = 0x61C88647;
unsigned int sum ,v1 ,v0;
unsigned char key0[]="{you_find_it_!?}";
unsigned int *key=(unsigned int *)key0;
for (int j = 0; j < 12; j+=2)
{
sum = -32 * delta;
v1=k[j];
v0=k[j+1];
for (int i = 0; i < 32; i++)
{
v0 -= ( sum + key [ (sum >> 11) & 3 ] ) ^ ( v1 + ( ( 16 * v1 ) ^ ( v1 >> 5 ) ) ) ;
sum += delta ;
v1 -= ( sum + key [ sum & 3 ] ) ^ ( v0 + ( ( 16 * v0 ) ^ ( v0 >> 5 ) ) ) ;
}
k[j]=v1;
k[j+1]=v0;
}
写完xtea解密后再次观察,发现加密中还有两块异或,把数据dump出来解密
写此处解密脚本的时候要考虑加密逻辑和顺序的问题,由于加密的时候先进行xor1,再xtea,最后xor2,所以解密的时候要完全倒置,即xor2->xtea->xor1,所以可以写出如下脚本
#include<stdio.h>
int main()
{
char s[]="Laughter_is_poison_to_fear";
unsigned char enc[]
{
0x18, 0x09, 0x1C, 0x14, 0x37, 0x1D, 0x16, 0x2D, 0x3C, 0x05,
0x16, 0x3E, 0x02, 0x03, 0x10, 0x2C, 0x0E, 0x31, 0x39, 0x15,
0x04, 0x3A, 0x39, 0x03, 0x0D, 0x13, 0x2B, 0x3E, 0x06, 0x08,
0x37, 0x00, 0x17, 0x0B, 0x00, 0x1D, 0x1C, 0x00, 0x16, 0x06,
0x07, 0x17, 0x30, 0x03, 0x30, 0x06, 0x0A, 0x71
};
/////////////1
unsigned char xor1[] =
{
0xDA, 0x30, 0x23, 0xE3, 0xDC, 0x39, 0x82, 0x60, 0xA5, 0x44,
0x68, 0xC2, 0x43, 0x7A, 0xBB, 0xE4, 0x50, 0xE1, 0x02, 0xC2,
0x81, 0x59, 0xEA, 0x1E, 0xC6, 0x8B, 0x71, 0x38, 0x27, 0x83,
0x94, 0xD8, 0xF4, 0x8D, 0x1A, 0x2A, 0x56, 0x8A, 0x4A, 0xD4,
0x54, 0xDC, 0x24, 0x3F, 0xB9, 0xED, 0x7B, 0x9A
};
for(int i=0;i<48;i++)
{
enc[i]^=xor1[i];
}
unsigned int *k=(unsigned int *)enc;
unsigned int delta = 0x61C88647;
unsigned int sum ,v1 ,v0;
unsigned char key0[]="{you_find_it_!?}";
unsigned int *key=(unsigned int *)key0;
for (int j = 0; j < 12; j+=2)
{
sum = -32 * delta;
v1=k[j];
v0=k[j+1];
for (int i = 0; i < 32; i++)
{
v0 -= ( sum + key [ (sum >> 11) & 3 ] ) ^ ( v1 + ( ( 16 * v1 ) ^ ( v1 >> 5 ) ) ) ;
sum += delta ;
v1 -= ( sum + key [ sum & 3 ] ) ^ ( v0 + ( ( 16 * v0 ) ^ ( v0 >> 5 ) ) ) ;
}
k[j]=v1;
k[j+1]=v0;
}
//////2
for(int i=0;i<=47;i++)
{
enc[i]^=s[i%26];
}
for(int i=0;i<48;i++)
{
printf("%c",enc[i]);
}
return 0;
}
梭!😼
没想到梭出来还是fake flag,fakeflag_plz_Try_more_hard_to_find_the_true_flag
???
猜测有hook,选择动态调试观察加密逻辑
给加密函数尾部打上断点,单步步进调试
发现进入一块暂时不能反汇编的块,将其包装成函数观看
此处的VirtualProtect
函数修改了某个段的保护属性,说明后面将进入此处进行三次加密操作,其中第一个参数代表了该段的地址,第二个参数代表了该段的长度
在此次调试中,第一个参数的大小为0x671E30,这个参数在不同的调试进程中不同;而第二个参数,即段的长度固定,为0x4358
按g跳转到这个地址看看是怎么个事
手动按c分析一下,每一段包装成函数看看反汇编
可以看到这里近20000行代码中充斥着像这样的跳转块
且大致逻辑是在每一个块中进行一个异或计算,然后根据异或计算的结果来确定下一个运行的块的地址
此时我的想法是利用idc脚本,来自动化将这些块分析并包装,于是有了如下脚本
//自动分析脚本,由于每个块都以call $+5 pop ebx 开头,所以可以以此为特征进行判断
#include<idc.idc>
static main()
{
auto i,begin,end;
begin=0x671E30;
end=begin+0x4358;
for(i=begin;i<=end;i++)
{
if(Byte(i)==0 && Byte(i+1)==0xe8)
{
PatchByte(i,0x90);
MakeCode(i+1);
}
}
return 0;
}
分析完以后将其包装成函数
//先手动包装,然后观察特征值,充当条件
#include<idc.idc>
static main()
{
auto i,j,k,begin,end;
begin=0x671E30;
end=begin+0x4358;
i=begin;
while(i<end)
{
if(Byte(i)==0xe8 && Byte(i+1)==0 && Byte(i+2)==0 && Byte(i+3)==0 && Byte(i+4)==0 && Byte(i+5)==0x5b && Byte(i+6)==0x88)
{
for(j=i+1;j<=i+0x100;j++)
{
if(Byte(j-2)==0xff && Byte(j-1)==0xe3 && Byte(j)==0x00)
{
MakeFunction(i,j);
i=j;
break;
}
}
}
i++;
}
return 0;
}
包装完以后再手动进行一个查漏,但是发现仍然不能较好的反汇编,ida并不会自动将块与块之间的跳转计算掉
再次观察,发现一些可疑片段
在此处,popf popa
和pusha pushf
这两段语句经常成对出现,且中间往往夹有特殊的汇编代码,且这些代码并未在反汇编中展现出来,通过人肉阅读前面几个块,发现这部分代码似乎在构建一个数据集
为了把这些数据拿到手,选择使用x32dbg追踪进程
将可执行文件拖入x32dbg中,由于要调试的是第三次加密,所以先跳转到第二次加密处,在跳转处打上断点,运行到断点处
在ida中查找断点地址,为0x41F04F
跳转到该地址,打上断点
此时代码已经运行到了断点位置,即将进入加密逻辑块,选用跟踪的方式来获取指令信息,注意要调大最大步长,并且将暂停条件设置为代码运行出加密块的地址,即eip==0x41f082
运行追踪后可以在追踪界面中看到所有指令
将他们导出到csv文件中,便于后期操作
会获得如下图的一个文件,其中每一行有7个数据
由于我们要获取的是popf popa
和pusha pushf
之间的语句,所以仅获取汇编部分即可;此处要注意的是,由于汇编代码中操作数间的分割也用逗号,所以在脚本中要作出一些特殊处理,分辨操作数间的逗号和正常间隔的逗号
code = []
def read_datas(fp):
with open(fp,'r',encoding='utf-8') as file:
lines = file.readlines()
global code
for i in range(len(lines)):
line = lines[i]
parts = line.strip().split(',')
if len(parts)==8:
parts[3]+=','+parts[4]
if parts[3][0]=='\"':
parts[3]=parts[3][1:]
if parts[3][-1]=='\"':
parts[3]=parts[3][:-1]
code.append(parts[3])
def write_datas(fp2):
global code
flag=0
with open(fp2,'w+',encoding='utf-8') as file2:
for i in range(len(code)):
if "pushad" in code[i]:
flag=0
else:
if "popad" in code[i-1]:
flag=1
if flag:
file2.write(code[i])
file2.write('\n')
file_addr="F:\CTF\GAMES\DASCTF2024\刻板印象re\export-20241229-201158.csv"
file_addr2="F:\CTF\GAMES\DASCTF2024\刻板印象re\export_re.txt"
read_datas(file_addr)
write_datas(file_addr2)
运行后即可获得有用的代码段
将这个汇编代码段反汇编处理,得到如下的代码
#include <iostream>
// 假设这个函数接受一个整数数组作为参数,类似于汇编中通过栈传递参数的方式
void processArray(int* arr) {
int localVar = 0xC; // 对应汇编中的 [ebp - 14]
int* eax = arr; // 对应汇编中的 [ebp + 8],假设为数组指针
int* ebp_10 = eax; // 对应汇编中的 [ebp - 10]
// 以下是对应汇编中初始化字节数组的部分,这里使用一个字符数组来模拟
char byteArray[] = {0x7B, 0x57, 0x68, 0x61, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x74, 0x68, 0x69, 0x73, 0x5F, 0x3F, 0x7D};
int* ebp_28 = &byteArray[0];
int edx = localVar;
if (edx == 1) {
int eaxVal = 34;
int quotient = eaxVal / edx;
int result = quotient + 6;
int* ebp_1C = &result;
int* ebp_18 = &localVar;
*ebp_18 = 0;
// 以下是一段复杂的计算逻辑,涉及数组索引和位运算,这里简化为一个循环计算示例
for (int i = 0; i < edx; i++) {
int ecx = eax[i];
int* ebp_8 = &ecx;
int edxVal = edx;
int eaxVal2 = eax[edxVal - 1];
int* ebp_C = &eaxVal2;
int eaxShifted = *ebp_8 >> 5;
int ecxShifted = *ebp_C << 2;
int xorResult1 = eaxShifted ^ ecxShifted;
int ecxShifted2 = *ebp_C >> 3;
int eaxShifted2 = *ebp_8 << 4;
int xorResult2 = ecxShifted2 ^ eaxShifted2;
int sum = xorResult1 + xorResult2;
int edxVal2 = *ebp_18;
int xorResult3 = edxVal2 ^ *ebp_C;
int ecxAnd = i & 3;
int xorResult4 = ecxAnd ^ (*ebp_24); // 假设ebp_24在之前有正确的初始化,这里简化处理
int esi = *ebp_28;
int ecxVal = *((int*)esi + ecxAnd);
int xorResult5 = ecxVal ^ *ebp_8;
int edxVal3 = edxVal2 ^ ecxVal;
int xorResult6 = sum ^ edxVal3;
int eaxVal3 = eax[i];
int edxVal4 = eaxVal3 ^ xorResult6;
eax[i] = edxVal4;
*ebp_8 = eax[i];
i++;
}
}
// 以下是另一段类似的计算逻辑,与上面的部分有相似之处,也简化为循环计算示例
int ebp_1CVal = *ebp_1C;
ebp_1CVal--;
*ebp_1C = ebp_1CVal;
int ebp_18Val = *ebp_18;
ebp_18Val += 11451419;
*ebp_18 = ebp_18Val;
int eaxVal4 = *ebp_18;
int andResult = eaxVal4 >> 2 & 3;
int* ebp_24 = &andResult;
int* ebp_4 = &localVar;
*ebp_4 = 0;
for (int i = 0; i < edx - 1; i++) {
int eaxVal5 = eax[i];
int ecxVal2 = eax[eaxVal5 + 4];
int* ebp_C2 = &ecxVal2;
int edxVal5 = *ebp_8;
int eaxShifted3 = edxVal5 >> 5;
int ecxShifted3 = *ebp_C2 << 2;
int xorResult7 = eaxShifted3 ^ ecxShifted3;
int ecxShifted4 = *ebp_C2 >> 3;
int eaxShifted4 = edxVal5 << 4;
int xorResult8 = ecxShifted4 ^ eaxShifted4;
int sum2 = xorResult7 + xorResult8;
int edxVal6 = *ebp_18;
int xorResult9 = edxVal6 ^ *ebp_C2;
int ecxAnd2 = i & 3;
int xorResult10 = ecxAnd2 ^ (*ebp_24);
int esi2 = *ebp_28;
int ecxVal3 = *((int*)esi2 + ecxAnd2);
int xorResult11 = ecxVal3 ^ *ebp_8;
int edxVal7 = edxVal6 ^ ecxVal3;
int xorResult12 = sum2 ^ edxVal7;
int eaxVal6 = eax[i];
int edxVal8 = eaxVal6 ^ xorResult12;
eax[i] = edxVal8;
*ebp_8 = eax[i];
i++;
}
// 以下是一些字节数组操作的模拟,假设是对输入数组进行某种加密或转换
char encryptedArray[] = {0x8F, 0x6C, 0xA6, 0x3F, 0x94, 0x3D, 0xF5, 0xD9, 0x36, 0x66, 0x51, 0xD7, 0x66, 0x2F, 0xB3, 0x8F, 0xC0, 0x61, 0x9E, 0xCE, 0xE9, 0xD7, 0xE1, 0xBF, 0x13, 0x14, 0x16, 0x14, 0xC2, 0xE7, 0xC3, 0x3A, 0x7F, 0x94, 0xA1, 0xE7, 0x24, 0xE, 0xA7, 0x5C, 0xD3, 0x77, 0xFE, 0x4F, 0x11, 0xDC, 0x69, 0x23};
int* ebp_20 = &localVar;
for (int i = 0; i < 30; i++) {
int ecxVal4 = encryptedArray[i];
int edxVal9 = eax[i];
int xorResult13 = ecxVal4 ^ edxVal9;
eax[i] = xorResult13;
i++;
}
}
是一个xxtea的加密操作,外加一个xor3的加密
故加密逻辑已知,是xor1->xtea->xor2->xxtea->xor3,可写出解密脚本
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char xor_3[] = {0x8F, 0x6C, 0xA6, 0x3F, 0x94, 0x3D, 0xF5, 0xD9, 0x36, 0x66,
0x51, 0xD7, 0x66, 0x2F, 0xB3, 0x8F, 0xC0, 0x61, 0x9E, 0xCE,
0xE9, 0xD7, 0xE1, 0xBF, 0x13, 0x14, 0x16, 0x14, 0xC2, 0xE7,
0xC3, 0x3A, 0x7F, 0x94, 0xA1, 0xE7, 0x24, 0xE , 0xA7, 0x5C,
0xD3, 0x77, 0xFE, 0x4F, 0x11, 0xDC, 0x69, 0x23};
unsigned char enc[]
{
0x18, 0x09, 0x1C, 0x14, 0x37, 0x1D, 0x16, 0x2D, 0x3C, 0x05,
0x16, 0x3E, 0x02, 0x03, 0x10, 0x2C, 0x0E, 0x31, 0x39, 0x15,
0x04, 0x3A, 0x39, 0x03, 0x0D, 0x13, 0x2B, 0x3E, 0x06, 0x08,
0x37, 0x00, 0x17, 0x0B, 0x00, 0x1D, 0x1C, 0x00, 0x16, 0x06,
0x07, 0x17, 0x30, 0x03, 0x30, 0x06, 0x0A, 0x71
};
for(int i=0;i<=47;i++)
{
enc[i]^=xor_3[i];
}
printf("\n");
unsigned int *v = (unsigned int*)enc;
unsigned char key_3[] = {0x7B, 0x57, 0x68, 0x61,
0x74, 0x5F, 0x69, 0x73,
0x5F, 0x74, 0x68, 0x69,
0x73, 0x5F, 0x3F, 0x7D};
unsigned int *key = (unsigned int *)key_3;
unsigned int delta = 0x11451419;
unsigned int sum = 0;
unsigned int y,z,p,rounds,e;
int n = 12;
int i = 0;
rounds = 6 + 52/n;
sum = rounds * delta;
y = v[0];
sum = rounds*delta;
do
{
e = sum >> 2 & 3;
for(p=n-1;p>0;p--)
{
z = v[p-1];
v[p] -= ((((z>>5)^(y<<2))+((y>>3)^(z<<4))) ^ ((key[(p&3)^e]^z)+(y ^ sum)));
y = v[p];
}
z = v[n-1];
v[0] -= (((key[(p^e)&3]^z)+(y ^ sum)) ^ (((y<<2)^(z>>5))+((z<<4)^(y>>3))));
y = v[0];
sum = sum-delta;
}while(--rounds);
unsigned char xor1[] =
{
0xDA, 0x30, 0x23, 0xE3, 0xDC, 0x39, 0x82, 0x60, 0xA5, 0x44,
0x68, 0xC2, 0x43, 0x7A, 0xBB, 0xE4, 0x50, 0xE1, 0x02, 0xC2,
0x81, 0x59, 0xEA, 0x1E, 0xC6, 0x8B, 0x71, 0x38, 0x27, 0x83,
0x94, 0xD8, 0xF4, 0x8D, 0x1A, 0x2A, 0x56, 0x8A, 0x4A, 0xD4,
0x54, 0xDC, 0x24, 0x3F, 0xB9, 0xED, 0x7B, 0x9A
};
for(int i=0;i<48;i++)
{
enc[i]^=xor1[i];
}
unsigned int *k=(unsigned int *)enc;
delta = 0x61C88647;
unsigned int v1 ,v0;
unsigned char key0[]="{you_find_it_!?}";
key=(unsigned int *)key0;
for (int j = 0; j < 12; j+=2)
{
sum = -32 * delta;
v1=k[j];
v0=k[j+1];
for (int i = 0; i < 32; i++)
{
v0 -= ( sum + key [ (sum >> 11) & 3 ] ) ^ ( v1 + ( ( 16 * v1 ) ^ ( v1 >> 5 ) ) ) ;
sum += delta ;
v1 -= ( sum + key [ sum & 3 ] ) ^ ( v0 + ( ( 16 * v0 ) ^ ( v0 >> 5 ) ) ) ;
}
k[j]=v1;
k[j+1]=v0;
}
//////2
char s[]="Laughter_is_poison_to_fear";
for(int i=0;i<=47;i++)
{
enc[i]^=s[i%26];
}
for(int i=0;i<48;i++)
{
printf("%c",enc[i]);
}
return 0;
}
得到flag为DASCTF{You_come_to_me_better_than_all_the_good.}
题目:黑客不许哭
拿到题目直接在头上看到这个,IsDebuggerPresent
,很明显是一个反调试,所以先去把它过掉
看一眼汇编,逻辑是步进到exit
块里面退出,还有一个int 3
来保证调试器退出。这里官方wp是把jz
语句换成了jmp
,来确保跳转到下面的正常语句;我比较懒,选择把他们全部nop
掉
接下来看代码主体部分,首先去关心最后面的判断部分,可见是v16和v17的比较,即qword_14002A170[v15]
和*(double *)&v4[8 * v15]
的比较
这里值得关注的一点就是代码将比较数据特意化为了double型,这点需要记住,后面要用
点进去看一下数据,就知道了qword_14002A170[v15]
就是密文
观察这个数据,其中大量出现了0x40这个数据,结合上文中出现的double,推断出这是一个实数表,将这些数据dump下来转化看看
unsigned char c1[] =
{
0x85, 0x25, 0x1E, 0x50, 0x96, 0x06, 0xB1, 0x40, 0x66, 0x88,
0x63, 0x5D, 0x4C, 0xEA, 0xB7, 0x40, 0xA3, 0x1E, 0xA2, 0xD1,
0x7D, 0xDD, 0xA0, 0x40, 0x78, 0x09, 0x4E, 0x7D, 0x04, 0x55,
0xB7, 0x40, 0x6A, 0x15, 0xFD, 0xA1, 0xEB, 0xEA, 0xC1, 0x40,
0xDC, 0x4B, 0x1A, 0xA3, 0xAD, 0x14, 0xB8, 0x40, 0xA1, 0x47,
0x8C, 0x9E, 0xC3, 0x02, 0xC8, 0x40, 0xDF, 0xA8, 0x15, 0xA6,
0xA7, 0xF6, 0xAF, 0x40, 0x46, 0x43, 0xC6, 0xA3, 0x64, 0x41,
0xAA, 0x40, 0xC1, 0x91, 0x40, 0x83, 0x55, 0xC7, 0xA2, 0x40,
0x53, 0x40, 0xDA, 0xFF, 0xE8, 0xFE, 0xA8, 0x40, 0x05, 0x19,
0x01, 0x15, 0x1E, 0x62, 0xB3, 0x40, 0xDC, 0x2C, 0x5E, 0x2C,
0x34, 0x25, 0xC0, 0x40, 0xA9, 0xC0, 0xC9, 0x36, 0x20, 0x5E,
0xA6, 0x40, 0x28, 0x2D, 0x5C, 0x56, 0x81, 0x52, 0x90, 0x40,
0x52, 0xF5, 0x2B, 0x9D, 0x1F, 0xAE, 0x90, 0x40, 0xED, 0x7E,
0x15, 0xE0, 0xF3, 0x22, 0xA9, 0x40, 0x78, 0xD2, 0xC2, 0x65,
0xF1, 0x74, 0xB8, 0x40, 0x6F, 0x2E, 0xFE, 0xB6, 0xE7, 0x9D,
0xA9, 0x40, 0x90, 0xDB, 0x2F, 0x9F, 0x2C, 0x17, 0x64, 0x40,
0x2A, 0xC5, 0x8E, 0xC6, 0x61, 0xA6, 0x82, 0x40, 0xEC, 0x13,
0x40, 0x31, 0xF2, 0x9B, 0xA9, 0x40, 0x84, 0x49, 0xF1, 0xF1,
0xC1, 0xE0, 0xB8, 0x40, 0x3A, 0x5B, 0x40, 0x68, 0xDD, 0x56,
0x8A, 0x40, 0x32, 0x1C, 0xCF, 0x67, 0x24, 0x25, 0xB7, 0x40,
0x1C, 0x9A, 0xB2, 0xD3, 0xDF, 0xCD, 0xA7, 0x40, 0x58, 0x74,
0xEB, 0x35, 0x31, 0xE8, 0xC8, 0x40, 0x15, 0xE3, 0xFC, 0x4D,
0x18, 0x15, 0xA3, 0x40, 0x3C, 0xDE, 0xE4, 0xB7, 0xA8, 0x8C,
0x9C, 0x40, 0x56, 0x64, 0x74, 0x40, 0xF6, 0x27, 0xB3, 0x40,
0xAB, 0x7A, 0xF9, 0x9D, 0xDE, 0xF3, 0xB5, 0x40, 0x4F, 0x90,
0xD8, 0xEE, 0x7E, 0x16, 0xAE, 0x40, 0x17, 0xB8, 0x3C, 0xD6,
0xFC, 0x78, 0xB1, 0x40, 0xA6, 0xF2, 0x76, 0x84, 0xD1, 0xA7,
0xC9, 0x40, 0xB9, 0x8E, 0x71, 0xC5, 0x85, 0xA2, 0x99, 0x40,
0xB6, 0x47, 0x6F, 0xB8, 0x6F, 0x7B, 0x8E, 0x40, 0xA3, 0x21,
0xE3, 0x51, 0xC2, 0xFC, 0xA0, 0x40, 0x6F, 0x2D, 0x93, 0xE1,
0xB0, 0xE3, 0xA1, 0x40, 0xB3, 0xED, 0xB4, 0x35, 0x6A, 0x5B,
0xA4, 0x40, 0x08, 0x02, 0x64, 0xE8, 0x58, 0x42, 0x97, 0x40,
0xB1, 0x19, 0xE0, 0x82, 0x02, 0xDC, 0xC7, 0x40, 0x05, 0xA3,
0x92, 0x3A, 0x45, 0xEC, 0xB1, 0x40, 0xE3, 0x88, 0xB5, 0xF8,
0x5C, 0xC3, 0xB2, 0x40, 0x65, 0x70, 0x94, 0xBC, 0xA6, 0x75,
0xC9, 0x40, 0xDA, 0xC0, 0xDA, 0xC0, 0x36, 0xD0, 0x89, 0xC6,
0x3F, 0xD2, 0x40, 0xFF, 0x9F, 0x86, 0xB7, 0xCE, 0x6A, 0x77,
0xF0, 0x35, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00
};
printf("\n");
double *enc = (double *)c1;
for(int i=0;i<44;i++)
{
printf("%10.6lf\n",enc[i]);
}
运行后很明显得到了密文
所以v4中存放的是加密后的flag数据,此时通过动态调试观察数据去向
动调采用的数据:01324567980123456789012345678901234567980123
在动调过程中dump下需要的数据,写脚本分析
#include <iostream>
int main()
{
unsigned char read_1[]="01324567980123456789012345678901234567980123";
unsigned char c1[] =
{
0x85, 0x25, 0x1E, 0x50, 0x96, 0x06, 0xB1, 0x40, 0x66, 0x88,
0x63, 0x5D, 0x4C, 0xEA, 0xB7, 0x40, 0xA3, 0x1E, 0xA2, 0xD1,
0x7D, 0xDD, 0xA0, 0x40, 0x78, 0x09, 0x4E, 0x7D, 0x04, 0x55,
0xB7, 0x40, 0x6A, 0x15, 0xFD, 0xA1, 0xEB, 0xEA, 0xC1, 0x40,
0xDC, 0x4B, 0x1A, 0xA3, 0xAD, 0x14, 0xB8, 0x40, 0xA1, 0x47,
0x8C, 0x9E, 0xC3, 0x02, 0xC8, 0x40, 0xDF, 0xA8, 0x15, 0xA6,
0xA7, 0xF6, 0xAF, 0x40, 0x46, 0x43, 0xC6, 0xA3, 0x64, 0x41,
0xAA, 0x40, 0xC1, 0x91, 0x40, 0x83, 0x55, 0xC7, 0xA2, 0x40,
0x53, 0x40, 0xDA, 0xFF, 0xE8, 0xFE, 0xA8, 0x40, 0x05, 0x19,
0x01, 0x15, 0x1E, 0x62, 0xB3, 0x40, 0xDC, 0x2C, 0x5E, 0x2C,
0x34, 0x25, 0xC0, 0x40, 0xA9, 0xC0, 0xC9, 0x36, 0x20, 0x5E,
0xA6, 0x40, 0x28, 0x2D, 0x5C, 0x56, 0x81, 0x52, 0x90, 0x40,
0x52, 0xF5, 0x2B, 0x9D, 0x1F, 0xAE, 0x90, 0x40, 0xED, 0x7E,
0x15, 0xE0, 0xF3, 0x22, 0xA9, 0x40, 0x78, 0xD2, 0xC2, 0x65,
0xF1, 0x74, 0xB8, 0x40, 0x6F, 0x2E, 0xFE, 0xB6, 0xE7, 0x9D,
0xA9, 0x40, 0x90, 0xDB, 0x2F, 0x9F, 0x2C, 0x17, 0x64, 0x40,
0x2A, 0xC5, 0x8E, 0xC6, 0x61, 0xA6, 0x82, 0x40, 0xEC, 0x13,
0x40, 0x31, 0xF2, 0x9B, 0xA9, 0x40, 0x84, 0x49, 0xF1, 0xF1,
0xC1, 0xE0, 0xB8, 0x40, 0x3A, 0x5B, 0x40, 0x68, 0xDD, 0x56,
0x8A, 0x40, 0x32, 0x1C, 0xCF, 0x67, 0x24, 0x25, 0xB7, 0x40,
0x1C, 0x9A, 0xB2, 0xD3, 0xDF, 0xCD, 0xA7, 0x40, 0x58, 0x74,
0xEB, 0x35, 0x31, 0xE8, 0xC8, 0x40, 0x15, 0xE3, 0xFC, 0x4D,
0x18, 0x15, 0xA3, 0x40, 0x3C, 0xDE, 0xE4, 0xB7, 0xA8, 0x8C,
0x9C, 0x40, 0x56, 0x64, 0x74, 0x40, 0xF6, 0x27, 0xB3, 0x40,
0xAB, 0x7A, 0xF9, 0x9D, 0xDE, 0xF3, 0xB5, 0x40, 0x4F, 0x90,
0xD8, 0xEE, 0x7E, 0x16, 0xAE, 0x40, 0x17, 0xB8, 0x3C, 0xD6,
0xFC, 0x78, 0xB1, 0x40, 0xA6, 0xF2, 0x76, 0x84, 0xD1, 0xA7,
0xC9, 0x40, 0xB9, 0x8E, 0x71, 0xC5, 0x85, 0xA2, 0x99, 0x40,
0xB6, 0x47, 0x6F, 0xB8, 0x6F, 0x7B, 0x8E, 0x40, 0xA3, 0x21,
0xE3, 0x51, 0xC2, 0xFC, 0xA0, 0x40, 0x6F, 0x2D, 0x93, 0xE1,
0xB0, 0xE3, 0xA1, 0x40, 0xB3, 0xED, 0xB4, 0x35, 0x6A, 0x5B,
0xA4, 0x40, 0x08, 0x02, 0x64, 0xE8, 0x58, 0x42, 0x97, 0x40,
0xB1, 0x19, 0xE0, 0x82, 0x02, 0xDC, 0xC7, 0x40, 0x05, 0xA3,
0x92, 0x3A, 0x45, 0xEC, 0xB1, 0x40, 0xE3, 0x88, 0xB5, 0xF8,
0x5C, 0xC3, 0xB2, 0x40, 0x65, 0x70, 0x94, 0xBC, 0xA6, 0x75,
0xC9, 0x40, 0xDA, 0xC0, 0xDA, 0xC0, 0x36, 0xD0, 0x89, 0xC6,
0x3F, 0xD2, 0x40, 0xFF, 0x9F, 0x86, 0xB7, 0xCE, 0x6A, 0x77,
0xF0, 0x35, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00
};
double *enc = (double *)c1;
unsigned char c2[] =
{
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0x7B, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0xFE, 0x48, 0x40, 0x1D, 0x2D, 0x52, 0xAD,
0x5D, 0x03, 0x4A, 0x40, 0xD6, 0xC7, 0x87, 0x45, 0xCA, 0x80,
0x49, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x85, 0x4A, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x08, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x8B, 0x4B, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x0D, 0x4C, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x12,
0x4D, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x90, 0x4C, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0x7B, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0xFE, 0x48, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x80, 0x49, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x03,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x85, 0x4A, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x08, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x8B, 0x4B, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x0D, 0x4C, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x90,
0x4C, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x12, 0x4D, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0x7B, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0xFE, 0x48, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x80, 0x49, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x03,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x85, 0x4A, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x08, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x8B, 0x4B, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x0D, 0x4C, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x90,
0x4C, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x12, 0x4D, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0x7B, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0xFE, 0x48, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x80, 0x49, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x03,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x85, 0x4A, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x08, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x8B, 0x4B, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x0D, 0x4C, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x12,
0x4D, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x90, 0x4C, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0x7B, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0xFE, 0x48, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x80, 0x49, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x03,
0x4A, 0x40
};
double *enc2 = (double *)c2;
unsigned char c3[] =
{
0xBB, 0x0B, 0x6E, 0x04, 0x5D, 0x42, 0x4E, 0x40, 0xB8, 0xD8,
0xF5, 0x2B, 0x51, 0x5E, 0x56, 0x40, 0x72, 0x38, 0x21, 0xB4,
0xF2, 0x07, 0x38, 0x40, 0xEC, 0x17, 0x75, 0x44, 0x14, 0x2C,
0x55, 0x40, 0x89, 0x42, 0x65, 0xAF, 0xD9, 0x2A, 0x5A, 0x40,
0x59, 0x3C, 0x61, 0xD7, 0x66, 0xF0, 0x54, 0x40, 0xA1, 0xB3,
0xE4, 0xA6, 0x44, 0x1A, 0x58, 0x40, 0xFE, 0xF1, 0x07, 0x75,
0x53, 0xD1, 0x52, 0x40, 0xFB, 0x98, 0xC2, 0x8D, 0x6B, 0x2A,
0x4E, 0x40, 0x73, 0x46, 0x8C, 0xC5, 0x68, 0x0D, 0x47, 0x40,
0xDB, 0x26, 0x1F, 0x86, 0x8F, 0x24, 0x4C, 0x40, 0x6B, 0x80,
0x98, 0x8D, 0x1E, 0xAC, 0x55, 0x40, 0x0C, 0x1D, 0xA7, 0xE9,
0x2E, 0x38, 0x54, 0x40, 0xC4, 0x4E, 0x56, 0xC8, 0x43, 0xA6,
0x4B, 0x40, 0x8D, 0x83, 0x83, 0xE4, 0x03, 0x86, 0x22, 0x40,
0xAF, 0xC6, 0x7C, 0x03, 0x91, 0xA0, 0x34, 0x40, 0xF5, 0x55,
0x0B, 0xEE, 0x92, 0x30, 0x3F, 0x40, 0x4A, 0xB0, 0x91, 0x99,
0xF0, 0x0B, 0x5D, 0x40, 0x5A, 0x40, 0x70, 0x9A, 0x23, 0xDC,
0x3E, 0x40, 0x4C, 0x08, 0xB3, 0xA0, 0x75, 0x03, 0xF1, 0x3F,
0x70, 0xCA, 0xE7, 0x3D, 0xD2, 0x2E, 0x25, 0x40, 0xCF, 0x58,
0x24, 0xD1, 0x27, 0xD3, 0x4B, 0x40, 0xF6, 0x21, 0x91, 0x22,
0xD4, 0xBC, 0x5E, 0x40, 0xA6, 0x7F, 0x64, 0x2C, 0x03, 0x90,
0x1C, 0x40, 0x65, 0x1A, 0x28, 0x19, 0x92, 0xB9, 0x4B, 0x40,
0x59, 0x3E, 0xDC, 0x68, 0xDC, 0x69, 0x4F, 0x40, 0xAA, 0xF1,
0x05, 0x64, 0x91, 0x53, 0x5F, 0x40, 0xB0, 0x08, 0xCB, 0x89,
0xF1, 0xF8, 0x46, 0x40, 0xCF, 0xAE, 0x46, 0x80, 0x32, 0x49,
0x40, 0x40, 0x18, 0x1F, 0x05, 0xE2, 0xDD, 0x17, 0x57, 0x40,
0x87, 0x53, 0xBC, 0x70, 0x8D, 0x6B, 0x5D, 0x40, 0x6F, 0xAE,
0x0D, 0xB0, 0x11, 0xB6, 0x4F, 0x40, 0x1B, 0x07, 0x86, 0xF3,
0x7F, 0x05, 0x55, 0x40, 0x87, 0x14, 0xFD, 0x3A, 0x6D, 0x53,
0x5F, 0x40, 0x9C, 0x12, 0x5F, 0x83, 0x2D, 0x81, 0x3A, 0x40,
0xAB, 0x92, 0x48, 0x37, 0x8F, 0x37, 0x2F, 0x40, 0x31, 0x04,
0xD1, 0x13, 0xF2, 0xD7, 0x41, 0x40, 0x8C, 0xF9, 0x91, 0xEB,
0x35, 0xD6, 0x42, 0x40, 0xBA, 0x2B, 0xE4, 0x05, 0x08, 0x53,
0x38, 0x40, 0xE6, 0x7F, 0xE1, 0xB0, 0x46, 0xB1, 0x39, 0x40,
0xB2, 0xFE, 0xB6, 0x5C, 0xAF, 0x1D, 0x5D, 0x40, 0x8B, 0x3B,
0x7A, 0x95, 0x5E, 0x93, 0x55, 0x40, 0x3C, 0xE9, 0x99, 0x20,
0x45, 0xE1, 0x53, 0x40, 0xD1, 0x9E, 0xE5, 0x34, 0xB6, 0x29,
0x59, 0x40
};
double *enc3 = (double *)c3;
unsigned char c4[] =
{
0xBB, 0x0B, 0x6E, 0x04, 0x5D, 0x42, 0x4E, 0x40, 0xB8, 0xD8,
0xF5, 0x2B, 0x51, 0x5E, 0x56, 0x40, 0x72, 0x38, 0x21, 0xB4,
0xF2, 0x07, 0x38, 0x40, 0xEC, 0x17, 0x75, 0x44, 0x14, 0x2C,
0x55, 0x40, 0x89, 0x42, 0x65, 0xAF, 0xD9, 0x2A, 0x5A, 0x40,
0x59, 0x3C, 0x61, 0xD7, 0x66, 0xF0, 0x54, 0x40, 0xA1, 0xB3,
0xE4, 0xA6, 0x44, 0x1A, 0x58, 0x40, 0xFE, 0xF1, 0x07, 0x75,
0x53, 0xD1, 0x52, 0x40, 0xFB, 0x98, 0xC2, 0x8D, 0x6B, 0x2A,
0x4E, 0x40, 0x73, 0x46, 0x8C, 0xC5, 0x68, 0x0D, 0x47, 0x40,
0xDB, 0x26, 0x1F, 0x86, 0x8F, 0x24, 0x4C, 0x40, 0x6B, 0x80,
0x98, 0x8D, 0x1E, 0xAC, 0x55, 0x40, 0x0C, 0x1D, 0xA7, 0xE9,
0x2E, 0x38, 0x54, 0x40, 0xC4, 0x4E, 0x56, 0xC8, 0x43, 0xA6,
0x4B, 0x40, 0x8D, 0x83, 0x83, 0xE4, 0x03, 0x86, 0x22, 0x40,
0xAF, 0xC6, 0x7C, 0x03, 0x91, 0xA0, 0x34, 0x40, 0xF5, 0x55,
0x0B, 0xEE, 0x92, 0x30, 0x3F, 0x40, 0x4A, 0xB0, 0x91, 0x99,
0xF0, 0x0B, 0x5D, 0x40, 0x5A, 0x40, 0x70, 0x9A, 0x23, 0xDC,
0x3E, 0x40, 0x4C, 0x08, 0xB3, 0xA0, 0x75, 0x03, 0xF1, 0x3F,
0x70, 0xCA, 0xE7, 0x3D, 0xD2, 0x2E, 0x25, 0x40, 0xCF, 0x58,
0x24, 0xD1, 0x27, 0xD3, 0x4B, 0x40, 0xF6, 0x21, 0x91, 0x22,
0xD4, 0xBC, 0x5E, 0x40, 0xA6, 0x7F, 0x64, 0x2C, 0x03, 0x90,
0x1C, 0x40, 0x65, 0x1A, 0x28, 0x19, 0x92, 0xB9, 0x4B, 0x40,
0x59, 0x3E, 0xDC, 0x68, 0xDC, 0x69, 0x4F, 0x40, 0xAA, 0xF1,
0x05, 0x64, 0x91, 0x53, 0x5F, 0x40, 0xB0, 0x08, 0xCB, 0x89,
0xF1, 0xF8, 0x46, 0x40, 0xCF, 0xAE, 0x46, 0x80, 0x32, 0x49,
0x40, 0x40, 0x18, 0x1F, 0x05, 0xE2, 0xDD, 0x17, 0x57, 0x40,
0x87, 0x53, 0xBC, 0x70, 0x8D, 0x6B, 0x5D, 0x40, 0x6F, 0xAE,
0x0D, 0xB0, 0x11, 0xB6, 0x4F, 0x40, 0x1B, 0x07, 0x86, 0xF3,
0x7F, 0x05, 0x55, 0x40, 0x87, 0x14, 0xFD, 0x3A, 0x6D, 0x53,
0x5F, 0x40, 0x9C, 0x12, 0x5F, 0x83, 0x2D, 0x81, 0x3A, 0x40,
0xAB, 0x92, 0x48, 0x37, 0x8F, 0x37, 0x2F, 0x40, 0x31, 0x04,
0xD1, 0x13, 0xF2, 0xD7, 0x41, 0x40, 0x8C, 0xF9, 0x91, 0xEB,
0x35, 0xD6, 0x42, 0x40, 0xBA, 0x2B, 0xE4, 0x05, 0x08, 0x53,
0x38, 0x40, 0xE6, 0x7F, 0xE1, 0xB0, 0x46, 0xB1, 0x39, 0x40,
0xB2, 0xFE, 0xB6, 0x5C, 0xAF, 0x1D, 0x5D, 0x40, 0x8B, 0x3B,
0x7A, 0x95, 0x5E, 0x93, 0x55, 0x40, 0x3C, 0xE9, 0x99, 0x20,
0x45, 0xE1, 0x53, 0x40, 0xD1, 0x9E, 0xE5, 0x34, 0xB6, 0x29,
0x59, 0x40
};
double *key = (double *)c4;
unsigned char c5[] =
{
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0xFB, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0x7E, 0x49, 0x40, 0x1D, 0x2D, 0x52, 0xAD,
0x5D, 0x83, 0x4A, 0x40, 0xD6, 0xC7, 0x87, 0x45, 0xCA, 0x00,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x05, 0x4B, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x88, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x0B, 0x4C, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x8D, 0x4C, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x92,
0x4D, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x10, 0x4D, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0xFB, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0x7E, 0x49, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x00, 0x4A, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x83,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x05, 0x4B, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x88, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x0B, 0x4C, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x8D, 0x4C, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x10,
0x4D, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x92, 0x4D, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0xFB, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0x7E, 0x49, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x00, 0x4A, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x83,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x05, 0x4B, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x88, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x0B, 0x4C, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x8D, 0x4C, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x10,
0x4D, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x92, 0x4D, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0xFB, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0x7E, 0x49, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x00, 0x4A, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x83,
0x4A, 0x40, 0x64, 0x92, 0x1C, 0x15, 0xF1, 0x05, 0x4B, 0x40,
0xAB, 0xF7, 0xE6, 0x7C, 0x84, 0x88, 0x4B, 0x40, 0xF2, 0x5C,
0xB1, 0xE4, 0x17, 0x0B, 0x4C, 0x40, 0x38, 0xC2, 0x7B, 0x4C,
0xAB, 0x8D, 0x4C, 0x40, 0xC6, 0x8C, 0x10, 0x1C, 0xD2, 0x92,
0x4D, 0x40, 0x7F, 0x27, 0x46, 0xB4, 0x3E, 0x10, 0x4D, 0x40,
0x48, 0xFD, 0xF2, 0x75, 0xA3, 0xFB, 0x48, 0x40, 0x8F, 0x62,
0xBD, 0xDD, 0x36, 0x7E, 0x49, 0x40, 0xD6, 0xC7, 0x87, 0x45,
0xCA, 0x00, 0x4A, 0x40, 0x1D, 0x2D, 0x52, 0xAD, 0x5D, 0x83,
0x4A, 0x40
};
double *enc4 = (double *)c5;
unsigned char ans[] =
{
0x01, 0x80, 0x7F, 0xDE, 0xB8, 0x67, 0xA8, 0x40, 0x10, 0xE6,
0x1D, 0x24, 0xE9, 0x35, 0xB2, 0x40, 0xB9, 0x6F, 0x2E, 0x15,
0x1C, 0x79, 0x95, 0x40, 0x74, 0xF5, 0xDF, 0x4B, 0x56, 0x98,
0xB1, 0x40, 0xF7, 0xC4, 0xFB, 0x81, 0x03, 0x7D, 0xB6, 0x40,
0x12, 0x51, 0x30, 0x2C, 0x2B, 0x68, 0xB2, 0x40, 0x32, 0x94,
0xC3, 0x18, 0x57, 0x83, 0xB5, 0x40, 0x28, 0x85, 0xB2, 0x19,
0x78, 0x2E, 0xB1, 0x40, 0xD1, 0xAC, 0x05, 0x14, 0xD9, 0xA8,
0xAC, 0x40, 0xDB, 0xDB, 0x42, 0xD3, 0xDA, 0xB7, 0xA5, 0x40,
0xAC, 0xD4, 0x51, 0x2C, 0xBA, 0xC0, 0xA6, 0x40, 0x15, 0x32,
0x8D, 0xBF, 0xF2, 0xA7, 0xB1, 0x40, 0xFB, 0xDA, 0x6E, 0xEC,
0x25, 0xD2, 0xB0, 0x40, 0x08, 0x1F, 0x39, 0xA9, 0x98, 0xB0,
0xA7, 0x40, 0x19, 0x79, 0xF0, 0xC6, 0x83, 0xC4, 0x82, 0x40,
0xF8, 0x5B, 0x19, 0x2A, 0x7A, 0x4F, 0x93, 0x40, 0x58, 0x50,
0x9C, 0x8C, 0x50, 0xE5, 0x9C, 0x40, 0x71, 0x8A, 0xBE, 0x9F,
0x0A, 0x4F, 0xBA, 0x40, 0x95, 0xDD, 0x21, 0xCE, 0x2A, 0x97,
0x9D, 0x40, 0x39, 0x99, 0xF7, 0x0B, 0x99, 0x5C, 0x64, 0x40,
0xB7, 0x5F, 0x16, 0x24, 0xB1, 0xA9, 0x83, 0x40, 0x3F, 0x0D,
0x4E, 0x3D, 0xB6, 0xF2, 0xA6, 0x40, 0xC9, 0x9B, 0xDA, 0xA6,
0x2E, 0x5E, 0xB9, 0x40, 0x9A, 0x86, 0x4C, 0xBE, 0x43, 0xEA,
0x7D, 0x40, 0x15, 0x9B, 0xEC, 0x23, 0xB9, 0x31, 0xA8, 0x40,
0x48, 0x9F, 0x81, 0xF0, 0x55, 0xCF, 0xAB, 0x40, 0x86, 0x22,
0x71, 0x55, 0xFB, 0xD7, 0xBB, 0x40, 0x82, 0x9C, 0x0B, 0x3A,
0x87, 0x47, 0xA5, 0x40, 0x2C, 0xF5, 0x22, 0x8E, 0x34, 0x25,
0x9F, 0x40, 0x79, 0xCA, 0x0C, 0x9A, 0x95, 0xBB, 0xB5, 0x40,
0x72, 0x9D, 0x42, 0xFA, 0x03, 0x5C, 0xB7, 0x40, 0x68, 0xD6,
0x2A, 0x16, 0x51, 0x0B, 0xAA, 0x40, 0x64, 0xA5, 0x41, 0xD6,
0xFC, 0x78, 0xB1, 0x40, 0xA2, 0x08, 0x38, 0xFB, 0x61, 0x58,
0xBA, 0x40, 0x19, 0xF4, 0x4F, 0x44, 0xEA, 0xF1, 0x97, 0x40,
0x22, 0x90, 0x57, 0x36, 0x0E, 0xFC, 0x8D, 0x40, 0xD7, 0x34,
0x49, 0x5F, 0x23, 0x6B, 0xA0, 0x40, 0x24, 0x72, 0x6B, 0xE1,
0xD3, 0x96, 0xA1, 0x40, 0xDC, 0x8A, 0x2B, 0xD0, 0xD9, 0x0A,
0x98, 0x40, 0x81, 0x44, 0xDB, 0x0B, 0xB3, 0xE5, 0x98, 0x40,
0xC5, 0x5A, 0x8F, 0x17, 0x39, 0x1F, 0xB7, 0x40, 0x20, 0x22,
0x65, 0x27, 0x3B, 0x94, 0xB1, 0x40, 0xDC, 0x82, 0xB3, 0xD3,
0x85, 0x8B, 0xB0, 0x40, 0x32, 0xC6, 0x66, 0x76, 0x30, 0x3D,
0xB5, 0x40
};
double *ans1 = (double *)ans;
printf("%15s | %8s %12s %12s %12s %12s %4s %12s %6s\n","enc","read","read_1","read_2","read_3","ans","i","read_1/read","read_2-read_1");
for(int i=0;i<44;i++)
{
printf("%15.8lf | %8d %12.6lf %12.6lf %12.6lf %12.6lf %4d %12.6lf %6.2lf\n",enc[i],read_1[i],enc2[i],enc4[i],enc3[i],ans1[i],i,enc2[i]/read_1[i],enc4[i]-enc2[i]);
}
return 0;
}
运行结果如下
结合动调的时候审计的代码和一些观察,可以猜测出加密逻辑的前两步,即脚本中的read_1/read
和read_2-read_1
逻辑,其中第一步的常数可以从代码中直接获取
故有
read->flag
flag*=1.020123456789000
flag+=1
'
由于flag的加密链如下
此时v8到v12的逻辑已经清晰了,但是到v4的逻辑还不清楚,所以要看看加密函数中的内容
函数中有一个显眼的字符串,cudaMemcpy
,故尝试用cuobjdump提取sass汇编
提取结果如下
Fatbin elf code:
================
arch = sm_52
code version = [1,7]
host = windows
compile_size = 64bit
code for sm_52
Function : _Z23vectorMulElementwiseGPUPKdS0_Pdi
.headerflags @"EF_CUDA_TEXMODE_UNIFIED EF_CUDA_64BIT_ADDRESS EF_CUDA_SM52 EF_CUDA_VIRTUAL_SM(EF_CUDA_SM52)"
/* 0x001cfc00e22007f6 */
/*0008*/ MOV R1, c[0x0][0x20] ; /* 0x4c98078000870001 */
/*0010*/ S2R R0, SR_CTAID.X ; /* 0xf0c8000002570000 */
/*0018*/ S2R R2, SR_TID.X ; /* 0xf0c8000002170002 */
/* 0x001fd842fec20ff1 */
/*0028*/ XMAD.MRG R3, R0.reuse, c[0x0] [0x8].H1, RZ ; /* 0x4f107f8000270003 */
/*0030*/ XMAD R2, R0.reuse, c[0x0] [0x8], R2 ; /* 0x4e00010000270002 */
/*0038*/ XMAD.PSL.CBCC R0, R0.H1, R3.H1, R2 ; /* 0x5b30011800370000 */
/* 0x001ff400fd4007ed */
/*0048*/ ISETP.GE.AND P0, PT, R0, c[0x0][0x158], PT ; /* 0x4b6d038005670007 */
/*0050*/ NOP ; /* 0x50b0000000070f00 */
/*0058*/ @P0 EXIT ; /* 0xe30000000000000f */
/* 0x081fd800fea207f1 */
/*0068*/ SHL R8, R0.reuse, 0x3 ; /* 0x3848000000370008 */
/*0070*/ SHR R0, R0, 0x1d ; /* 0x3829000001d70000 */
/*0078*/ IADD R4.CC, R8.reuse, c[0x0][0x140] ; /* 0x4c10800005070804 */
/* 0x001fd800fe0207f2 */
/*0088*/ IADD.X R5, R0.reuse, c[0x0][0x144] ; /* 0x4c10080005170005 */
/*0090*/ IADD R6.CC, R8, c[0x0][0x148] ; /* 0x4c10800005270806 */
/*0098*/ LDG.E.64 R4, [R4] ; /* 0xeed5200000070404 */
/* 0x001fd800f62007e2 */
/*00a8*/ IADD.X R7, R0, c[0x0][0x14c] ; /* 0x4c10080005370007 */
/*00b0*/ LDG.E.64 R2, [R6] ; /* 0xeed5200000070602 */
/*00b8*/ IADD R8.CC, R8, c[0x0][0x150] ; /* 0x4c10800005470808 */
/* 0x003fc420e28007f7 */
/*00c8*/ IADD.X R9, R0, c[0x0][0x154] ; /* 0x4c10080005570009 */
/*00d0*/ DFMA R2, R2, R4, c[0x2][0x0] ; /* 0x5370020800070202 */
/*00d8*/ STG.E.64 [R8], R2 ; /* 0xeedd200000070802 */
/* 0x001ffc00ffe007e8 */
/*00e8*/ NOP ; /* 0x50b0000000070f00 */
/*00f0*/ EXIT ; /* 0xe30000000007000f */
/*00f8*/ BRA 0xf8 ; /* 0xe2400fffff87000f */
..........
Function : _Z12vectorAddGPUPKdS0_Pdi
.headerflags @"EF_CUDA_TEXMODE_UNIFIED EF_CUDA_64BIT_ADDRESS EF_CUDA_SM52 EF_CUDA_VIRTUAL_SM(EF_CUDA_SM52)"
/* 0x001cfc00e22007f6 */
/*0008*/ MOV R1, c[0x0][0x20] ; /* 0x4c98078000870001 */
/*0010*/ S2R R0, SR_CTAID.X ; /* 0xf0c8000002570000 */
/*0018*/ S2R R2, SR_TID.X ; /* 0xf0c8000002170002 */
/* 0x001fd842fec20ff1 */
/*0028*/ XMAD.MRG R3, R0.reuse, c[0x0] [0x8].H1, RZ ; /* 0x4f107f8000270003 */
/*0030*/ XMAD R2, R0.reuse, c[0x0] [0x8], R2 ; /* 0x4e00010000270002 */
/*0038*/ XMAD.PSL.CBCC R0, R0.H1, R3.H1, R2 ; /* 0x5b30011800370000 */
/* 0x001ff400fd4007ed */
/*0048*/ ISETP.GE.AND P0, PT, R0, c[0x0][0x158], PT ; /* 0x4b6d038005670007 */
/*0050*/ NOP ; /* 0x50b0000000070f00 */
/*0058*/ @P0 EXIT ; /* 0xe30000000000000f */
/* 0x081fd800fea207f1 */
/*0068*/ SHL R8, R0.reuse, 0x3 ; /* 0x3848000000370008 */
/*0070*/ SHR R0, R0, 0x1d ; /* 0x3829000001d70000 */
/*0078*/ IADD R4.CC, R8.reuse, c[0x0][0x140] ; /* 0x4c10800005070804 */
/* 0x001fd800fe0207f2 */
/*0088*/ IADD.X R5, R0.reuse, c[0x0][0x144] ; /* 0x4c10080005170005 */
/*0090*/ IADD R6.CC, R8, c[0x0][0x148] ; /* 0x4c10800005270806 */
/*0098*/ LDG.E.64 R4, [R4] ; /* 0xeed5200000070404 */
/* 0x001fd800f62007e2 */
/*00a8*/ IADD.X R7, R0, c[0x0][0x14c] ; /* 0x4c10080005370007 */
/*00b0*/ LDG.E.64 R2, [R6] ; /* 0xeed5200000070602 */
/*00b8*/ IADD R8.CC, R8, c[0x0][0x150] ; /* 0x4c10800005470808 */
/* 0x003fc420e28007f7 */
/*00c8*/ IADD.X R9, R0, c[0x0][0x154] ; /* 0x4c10080005570009 */
/*00d0*/ DADD R2, R2, R4 ; /* 0x5c70000000470202 */
/*00d8*/ STG.E.64 [R8], R2 ; /* 0xeedd200000070802 */
/* 0x001ffc00ffe007e8 */
/*00e8*/ NOP ; /* 0x50b0000000070f00 */
/*00f0*/ EXIT ; /* 0xe30000000007000f */
/*00f8*/ BRA 0xf8 ; /* 0xe2400fffff87000f */
..........
Fatbin ptx code:
================
arch = sm_52
code version = [8,4]
host = windows
compile_size = 64bit
compressed
ptxasOptions =
反汇编,结果如下
// 假设这两个函数所在的命名空间等情况,根据实际可能需要调整
namespace {
// 对应汇编中的 _Z23vectorMulElementwiseGPUPKdS0_Pdi 函数,执行向量元素对应相乘操作
__global__ void vectorMulElementwiseGPU(const double* input1, const double* input2, double* output, int size) {
// 获取线程块在x维度的索引
int blockIdx_x = blockIdx.x;
// 获取线程在x维度的索引
int threadIdx_x = threadIdx.x;
// 计算全局线程索引(这里简单的一种计算方式示例,根据实际汇编中更复杂的计算逻辑调整)
int globalIdx = blockIdx_x * blockDim.x + threadIdx_x;
// 边界检查,如果超出了给定的数据范围则直接返回,避免越界访问等错误
if (globalIdx >= size) {
return;
}
// 从输入数组读取对应元素,这里假设汇编中复杂的地址计算就是为了定位到准确的输入元素位置
double element1 = input1[globalIdx];
double element2 = input2[globalIdx];
// 执行乘法操作,对应汇编中的乘法相关指令逻辑,这里只是简单的乘法示例,实际可能涉及更多常量等参与运算细节
double result = element1 * element2;
// 将结果存回输出数组相应位置,同样地址计算对应汇编中存储相关的地址操作逻辑
output[globalIdx] = result;
}
// 对应汇编中的 _Z12vectorAddGPUPKdS0_Pdi 函数,执行向量元素对应相加操作
__global__ void vectorAddGPU(const double* input1, const double* input2, double* output, int size) {
// 获取线程块在x维度的索引
int blockIdx_x = blockIdx.x;
// 获取线程在x维度的索引
int threadIdx_x = threadIdx.x;
// 计算全局线程索引(这里简单的一种计算方式示例,根据实际汇编中更复杂的计算逻辑调整)
int globalIdx = blockIdx_x * blockDim.x + threadIdx_x;
// 边界检查,如果超出了给定的数据范围则直接返回,避免越界访问等错误
if (globalIdx >= size) {
return;
}
// 从输入数组读取对应元素,这里假设汇编中复杂的地址计算就是为了定位到准确的输入元素位置
double element1 = input1[globalIdx];
double element2 = input2[globalIdx];
// 执行加法操作,对应汇编中的加法相关指令逻辑
double result = element1 + element2;
// 将结果存回输出数组相应位置,同样地址计算对应汇编中存储相关的地址操作逻辑
output[globalIdx] = result;
}
} // namespace
可以大致看出这里有两步加密操作,先是两数相乘,再是两数相加。在加密操作中还用到了预定义的一个密钥数组
经过尝试后得出最终加密逻辑
4. flag*=key
5. flag+=100
故可写出exp解密
#include<stdio.h>
#include<math.h>
int main()
{
unsigned char enc_data[] =
{
0x85, 0x25, 0x1E, 0x50, 0x96, 0x06, 0xB1, 0x40, 0x66, 0x88,
0x63, 0x5D, 0x4C, 0xEA, 0xB7, 0x40, 0xA3, 0x1E, 0xA2, 0xD1,
0x7D, 0xDD, 0xA0, 0x40, 0x78, 0x09, 0x4E, 0x7D, 0x04, 0x55,
0xB7, 0x40, 0x6A, 0x15, 0xFD, 0xA1, 0xEB, 0xEA, 0xC1, 0x40,
0xDC, 0x4B, 0x1A, 0xA3, 0xAD, 0x14, 0xB8, 0x40, 0xA1, 0x47,
0x8C, 0x9E, 0xC3, 0x02, 0xC8, 0x40, 0xDF, 0xA8, 0x15, 0xA6,
0xA7, 0xF6, 0xAF, 0x40, 0x46, 0x43, 0xC6, 0xA3, 0x64, 0x41,
0xAA, 0x40, 0xC1, 0x91, 0x40, 0x83, 0x55, 0xC7, 0xA2, 0x40,
0x53, 0x40, 0xDA, 0xFF, 0xE8, 0xFE, 0xA8, 0x40, 0x05, 0x19,
0x01, 0x15, 0x1E, 0x62, 0xB3, 0x40, 0xDC, 0x2C, 0x5E, 0x2C,
0x34, 0x25, 0xC0, 0x40, 0xA9, 0xC0, 0xC9, 0x36, 0x20, 0x5E,
0xA6, 0x40, 0x28, 0x2D, 0x5C, 0x56, 0x81, 0x52, 0x90, 0x40,
0x52, 0xF5, 0x2B, 0x9D, 0x1F, 0xAE, 0x90, 0x40, 0xED, 0x7E,
0x15, 0xE0, 0xF3, 0x22, 0xA9, 0x40, 0x78, 0xD2, 0xC2, 0x65,
0xF1, 0x74, 0xB8, 0x40, 0x6F, 0x2E, 0xFE, 0xB6, 0xE7, 0x9D,
0xA9, 0x40, 0x90, 0xDB, 0x2F, 0x9F, 0x2C, 0x17, 0x64, 0x40,
0x2A, 0xC5, 0x8E, 0xC6, 0x61, 0xA6, 0x82, 0x40, 0xEC, 0x13,
0x40, 0x31, 0xF2, 0x9B, 0xA9, 0x40, 0x84, 0x49, 0xF1, 0xF1,
0xC1, 0xE0, 0xB8, 0x40, 0x3A, 0x5B, 0x40, 0x68, 0xDD, 0x56,
0x8A, 0x40, 0x32, 0x1C, 0xCF, 0x67, 0x24, 0x25, 0xB7, 0x40,
0x1C, 0x9A, 0xB2, 0xD3, 0xDF, 0xCD, 0xA7, 0x40, 0x58, 0x74,
0xEB, 0x35, 0x31, 0xE8, 0xC8, 0x40, 0x15, 0xE3, 0xFC, 0x4D,
0x18, 0x15, 0xA3, 0x40, 0x3C, 0xDE, 0xE4, 0xB7, 0xA8, 0x8C,
0x9C, 0x40, 0x56, 0x64, 0x74, 0x40, 0xF6, 0x27, 0xB3, 0x40,
0xAB, 0x7A, 0xF9, 0x9D, 0xDE, 0xF3, 0xB5, 0x40, 0x4F, 0x90,
0xD8, 0xEE, 0x7E, 0x16, 0xAE, 0x40, 0x17, 0xB8, 0x3C, 0xD6,
0xFC, 0x78, 0xB1, 0x40, 0xA6, 0xF2, 0x76, 0x84, 0xD1, 0xA7,
0xC9, 0x40, 0xB9, 0x8E, 0x71, 0xC5, 0x85, 0xA2, 0x99, 0x40,
0xB6, 0x47, 0x6F, 0xB8, 0x6F, 0x7B, 0x8E, 0x40, 0xA3, 0x21,
0xE3, 0x51, 0xC2, 0xFC, 0xA0, 0x40, 0x6F, 0x2D, 0x93, 0xE1,
0xB0, 0xE3, 0xA1, 0x40, 0xB3, 0xED, 0xB4, 0x35, 0x6A, 0x5B,
0xA4, 0x40, 0x08, 0x02, 0x64, 0xE8, 0x58, 0x42, 0x97, 0x40,
0xB1, 0x19, 0xE0, 0x82, 0x02, 0xDC, 0xC7, 0x40, 0x05, 0xA3,
0x92, 0x3A, 0x45, 0xEC, 0xB1, 0x40, 0xE3, 0x88, 0xB5, 0xF8,
0x5C, 0xC3, 0xB2, 0x40, 0x65, 0x70, 0x94, 0xBC, 0xA6, 0x75,
0xC9, 0x40, 0xDA, 0xC0, 0xDA, 0xC0, 0x36, 0xD0, 0x89, 0xC6,
0x3F, 0xD2, 0x40, 0xFF, 0x9F, 0x86, 0xB7, 0xCE, 0x6A, 0x77,
0xF0, 0x35, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00
};
double *enc = (double *)enc_data;
unsigned char key_data[] =
{
0xBB, 0x0B, 0x6E, 0x04, 0x5D, 0x42, 0x4E, 0x40, 0xB8, 0xD8,
0xF5, 0x2B, 0x51, 0x5E, 0x56, 0x40, 0x72, 0x38, 0x21, 0xB4,
0xF2, 0x07, 0x38, 0x40, 0xEC, 0x17, 0x75, 0x44, 0x14, 0x2C,
0x55, 0x40, 0x89, 0x42, 0x65, 0xAF, 0xD9, 0x2A, 0x5A, 0x40,
0x59, 0x3C, 0x61, 0xD7, 0x66, 0xF0, 0x54, 0x40, 0xA1, 0xB3,
0xE4, 0xA6, 0x44, 0x1A, 0x58, 0x40, 0xFE, 0xF1, 0x07, 0x75,
0x53, 0xD1, 0x52, 0x40, 0xFB, 0x98, 0xC2, 0x8D, 0x6B, 0x2A,
0x4E, 0x40, 0x73, 0x46, 0x8C, 0xC5, 0x68, 0x0D, 0x47, 0x40,
0xDB, 0x26, 0x1F, 0x86, 0x8F, 0x24, 0x4C, 0x40, 0x6B, 0x80,
0x98, 0x8D, 0x1E, 0xAC, 0x55, 0x40, 0x0C, 0x1D, 0xA7, 0xE9,
0x2E, 0x38, 0x54, 0x40, 0xC4, 0x4E, 0x56, 0xC8, 0x43, 0xA6,
0x4B, 0x40, 0x8D, 0x83, 0x83, 0xE4, 0x03, 0x86, 0x22, 0x40,
0xAF, 0xC6, 0x7C, 0x03, 0x91, 0xA0, 0x34, 0x40, 0xF5, 0x55,
0x0B, 0xEE, 0x92, 0x30, 0x3F, 0x40, 0x4A, 0xB0, 0x91, 0x99,
0xF0, 0x0B, 0x5D, 0x40, 0x5A, 0x40, 0x70, 0x9A, 0x23, 0xDC,
0x3E, 0x40, 0x4C, 0x08, 0xB3, 0xA0, 0x75, 0x03, 0xF1, 0x3F,
0x70, 0xCA, 0xE7, 0x3D, 0xD2, 0x2E, 0x25, 0x40, 0xCF, 0x58,
0x24, 0xD1, 0x27, 0xD3, 0x4B, 0x40, 0xF6, 0x21, 0x91, 0x22,
0xD4, 0xBC, 0x5E, 0x40, 0xA6, 0x7F, 0x64, 0x2C, 0x03, 0x90,
0x1C, 0x40, 0x65, 0x1A, 0x28, 0x19, 0x92, 0xB9, 0x4B, 0x40,
0x59, 0x3E, 0xDC, 0x68, 0xDC, 0x69, 0x4F, 0x40, 0xAA, 0xF1,
0x05, 0x64, 0x91, 0x53, 0x5F, 0x40, 0xB0, 0x08, 0xCB, 0x89,
0xF1, 0xF8, 0x46, 0x40, 0xCF, 0xAE, 0x46, 0x80, 0x32, 0x49,
0x40, 0x40, 0x18, 0x1F, 0x05, 0xE2, 0xDD, 0x17, 0x57, 0x40,
0x87, 0x53, 0xBC, 0x70, 0x8D, 0x6B, 0x5D, 0x40, 0x6F, 0xAE,
0x0D, 0xB0, 0x11, 0xB6, 0x4F, 0x40, 0x1B, 0x07, 0x86, 0xF3,
0x7F, 0x05, 0x55, 0x40, 0x87, 0x14, 0xFD, 0x3A, 0x6D, 0x53,
0x5F, 0x40, 0x9C, 0x12, 0x5F, 0x83, 0x2D, 0x81, 0x3A, 0x40,
0xAB, 0x92, 0x48, 0x37, 0x8F, 0x37, 0x2F, 0x40, 0x31, 0x04,
0xD1, 0x13, 0xF2, 0xD7, 0x41, 0x40, 0x8C, 0xF9, 0x91, 0xEB,
0x35, 0xD6, 0x42, 0x40, 0xBA, 0x2B, 0xE4, 0x05, 0x08, 0x53,
0x38, 0x40, 0xE6, 0x7F, 0xE1, 0xB0, 0x46, 0xB1, 0x39, 0x40,
0xB2, 0xFE, 0xB6, 0x5C, 0xAF, 0x1D, 0x5D, 0x40, 0x8B, 0x3B,
0x7A, 0x95, 0x5E, 0x93, 0x55, 0x40, 0x3C, 0xE9, 0x99, 0x20,
0x45, 0xE1, 0x53, 0x40, 0xD1, 0x9E, 0xE5, 0x34, 0xB6, 0x29,
0x59, 0x40
};
double *key = (double *)key_data;
for(int i=0;i<44;i++)
{
//printf("%10.15lf %10.15lf\n",enc[i],key[i]);
enc[i]-=100;
enc[i]/=key[i];
enc[i]-=1;
enc[i]/=1.020123456789;
printf("%c",(int)round(enc[i]));
}
return 0;
}
解密后得到flag:DASCTF{34056b0c-a3d7-71ef-b132-92e8688d4e29}
题目:secret_of_inkey
打开题目所给的可执行文件,一共961个格子,每一个都能点,每一个都有对应的一个密码。
点击右上角的提示按钮,给出了565号格子的密码。
将这个密码填写进565格子中,得到了四个另外格子的密码
以此类推,所以这个程序的功能就类似于一个走迷宫的代码
目标:找到代码中产生返回数据的代码段,即加密函数
法一:长追踪(从secretbox按钮的点击方法开始追踪)
搜索字符串,直接就能看到提示按钮中的提示字符串,按x交叉引用勾进函数里面
这个函数的作用就是secretbox按钮的点击方法函数,功能相对较为详细,在流程中存在的位置应当较为枝叶,所以再次按x交叉引用返回上层
流程:sub_64C0
secretbox按钮点击方法->sub_415E90
初始化函数->sub_402350
加密流程主干
进入sub_402350
函数中,发现大量相似的块,共961个块,块的数量与格子数量相等,所以可以猜测这是每一个格子的加密算法
那么单次加密流程就应该在sub_416C40
函数中,进入观察
平平无奇,进入sub_417240
发现输入部分,向下翻找到加密函数sub_416D70
法二:近追踪(从输出框内容开始追踪)
由于输出框的标题为Right!
,所以直接在字符串中搜索Right!
,找到后交叉引用,进入加密函数sub_416D70
目标:分析加密函数
Decrypt1:
^(i%0x20)^key[i%0x10]
Decrypt2:
AES-ECB加密
即上面异或加密后进入的sub_401F90函数
目标:撰写脚本
故加密逻辑为循环加密,每轮先做一次异或,再做一次AES加密,每次加密获得的文本传入下一次加密作为密钥
而密文可以从加密部分的主干中看到,在内存中倒序放置,所以可以借助地址起始值和密文长度读取
地址起始值这里建议用010直接查看,ida中的地址还要考虑基址
from Crypto.Cipher import AES
datas=[]
f_number=[]
def Get_datas():
with open("inkey.exe","rb") as file:
file_read = file.read()
begin=0x3bf40
for i in range(961):
data_addr=begin-i*0x80
datas.append(file_read[data_addr:data_addr+0x80])
def decrypt(number ,key ):
if number in f_number :
return
f_number.append(number)
data=list(datas[number])
for i in range(len(data)):
data[i] = data[i] ^ (i%0x20) ^ key[i%0x10]
cipher = AES.new(key, AES.MODE_ECB)
data_re = cipher.decrypt(bytes(data))
keys=[]
numbers=[]
t=0
i=0
data_re_s=str(data_re)
while(i<len(data_re_s)):
if "DASCTF" in data_re_s :
print(data_re_s)
exit(0)
if data_re_s[i]=="\"":
keys.append(data_re_s[i+1:i+17])
while(t<i):
if data_re_s[t-1]=="_" and "0"<=data_re_s[t]<="9":
w=t
while("0"<=data_re_s[w]<="9"):
w+=1
numbers.append(data_re_s[t:w])
break
t+=1
i+=17
t=i+1
i+=1
if len(keys)==0 :
return
for i in range(len(keys)):
print(int(numbers[i]) ,bytes(keys[i],encoding="utf-8"),end=' ')
print('\n')
for i in range(len(keys)):
decrypt(int(numbers[i]) ,bytes(keys[i],encoding="utf-8") )
Get_datas()
decrypt(565 ,b'9fc82e15d9de6ef2')
解得flag=DASCTF{Do_y0u_l1ke_wh4t_you_s3e}