前言:新手一枚 能理解到的点我会写的很细 有问题可问 有错地方欢迎提出
0x00 日常查壳
无壳64位
0x01 主函数
先简单介绍一下smc,看了很多文章,意思大概就是自解码程序(运行过程中会有程序专门解数据),这种题动调最方便
分析一下主程序
1085地址和1d00的地址放在这两个地方(后面有用)
然后再经过一个1e30的加密函数
1085和1D00就是这串数据开始和结束的地方
0x02 1E30函数分析
进函数一看
想了解VirtualProtect往下看
这里就是对数据的修改 可以自己把数据拿出来自己改 也可以直接动调 我这边选择直接动调
VirtualProtect函数
0x03 动调
把断点断在解密前 查看变化
选择本地调试器
开始调试后有个输入是接受用户输入的 直接随便输入点进去
这边直接F8单步
因为下面不是代码区域 所以ida会报个错 直接否就可以
发现数据已经改变
然后从上往下 找到第一个retn 右键分析选择段
强制转换
直接F5反编译出
0x04 分析自解码后的程序
从头往下看会知道这是个又臭又长的程序
这种题目就是要做多了才有经验
随便挑一段看 会知道这是base64加密 但多了个异或操作
(没看出来的可以去看看用C写的base64加密脚本)
Buuctf-Reverse FlareOn3-Challenge Write up_水番正文的博客-CSDN博客
再翻翻会看到这个 既然有base64这个应该就是码表
整整齐齐
不难看出这是比较字符串
然后输出yes or no
现在来理一下
1.base64加密
2.修改了码表
3.加密完会有个异或
那么解密顺序就是
1.异或得出原来的数据
2.修改码表得到进行base64解密
0x05 GetFlag
#include <stdio.h>
#include <string.h>
int main(void)
{
unsigned char key[] = "H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4";
int data[] =
{
0xE4, 0xC4, 0xE7, 0xC7, 0xE6, 0xC6, 0xE1, 0xC1, 0xE0, 0xC0,
0xE3, 0xC3, 0xE2, 0xC2, 0xED, 0xCD, 0xEC, 0xCC, 0xEF, 0xCF,
0xEE, 0xCE, 0xE9, 0xC9, 0xE8, 0xC8, 0xEB, 0xCB, 0xEA, 0xCA,
0xF5, 0xD5, 0xF4, 0xD4, 0xF7, 0xD7, 0xF6, 0xD6, 0xF1, 0xD1,
0xF0, 0xD0, 0xF3, 0xD3, 0xF2, 0xD2, 0xFD, 0xDD, 0xFC, 0xDC,
0xFF, 0xDF, 0x95, 0x9C, 0x9D, 0x92, 0x93, 0x90, 0x91, 0x96,
0x97, 0x94, 0x8A, 0x8E
};
int xr[] = {0xA6, 0xA3, 0xA9, 0xAC};
int i, j;
unsigned int v3;
int flag[100] = {0};
for(i = 0; i < 56; i++)
{
key[i] ^= xr[i % 4];
// printf("%d ",key[i]);
}
// printf("\n");
for(i = 0; i < 56; i++)
for(j = 0; j < 64; j++)
if(key[i] == data[j])
{
key[i] = j;
// printf("%d:%d ",i,j);
break;
}
for(i = 0, j = 0; i < 56; i += 4, j += 3)
{
v3 = key[i+3] + (key[i+2] << 6) + (key[i+1] << 12) + (key[i] << 18);
flag[j] = (v3 >> 16) & 0xFF;
flag[j+1] = (v3 >> 8) & 0xFF;
flag[j+2] = v3 & 0xFF;
}
for(i = 0; i < 100; i++)
printf("%c",flag[i]);
return 0;
}
自己写的一个解密脚本 这篇文章写了心路历程
Buuctf-Reverse FlareOn3-Challenge Write up_水番正文的博客-CSDN博客
GetFlag!