目的:利用010,IDA分别进行对文件的改写和文件的反编译
010Editor 是一个全新的十六进位文件编辑器 它有别于传统的十六进位编辑器在于它可用'范本'来解析二进位文件, 从而让你读懂和编辑它. 它还可用来比较一切可视的二进位文件.
IDA(interactive Disassembler)交互式反汇编器,IDA最主要的特性是交互和多处理器。操作者可以通过对IDA的交互来指导IDA更好地反汇编,IDA并不自动解决程序中的问题,但它会按用户的指令找到可疑之处,用户的工作是通知IDA怎样去做。比如人工指定编译器类型,对变量名、结构定义、数组等定义等。这样的交互能力在反汇编大型软件时显得尤为重要。多处理器特点是指IDA支持常见处理器平台上的软件产品。IDA支持的文件类型非常丰富,除了常见的PE格式,还支持Windows,DOS,UNIX,Mac,Java,.NET等平台的文件格式
本文以该例题为例
兴趣是最好的老师--
首先将该PE文件改写为正确的,可运行的
然后运行文件,发现程序要求输入flag:
利用view-string,再利用search工具找到flag所在的函数
反编译后的伪C代码如下:
__int64 main_0()
{
int v0; // edx
__int64 v1; // ST00_8
int v3; // [esp+0h] [ebp-1A0h]
const char **v4; // [esp+4h] [ebp-19Ch]
const char **v5; // [esp+8h] [ebp-198h]
int v6; // [esp+Ch] [ebp-194h]
int i; // [esp+D4h] [ebp-CCh]
int v8; // [esp+E0h] [ebp-C0h]
int v9; // [esp+ECh] [ebp-B4h]
int v10; // [esp+F0h] [ebp-B0h]
int v11; // [esp+F4h] [ebp-ACh]
int v12; // [esp+F8h] [ebp-A8h]
int v13; // [esp+FCh] [ebp-A4h]
int v14; // [esp+100h] [ebp-A0h]
int v15; // [esp+104h] [ebp-9Ch]
int v16; // [esp+108h] [ebp-98h]
int v17; // [esp+10Ch] [ebp-94h]
int v18; // [esp+110h] [ebp-90h]
int v19; // [esp+114h] [ebp-8Ch]
int v20; // [esp+118h] [ebp-88h]
int v21; // [esp+11Ch] [ebp-84h]
int v22; // [esp+120h] [ebp-80h]
int v23; // [esp+124h] [ebp-7Ch]
int v24; // [esp+128h] [ebp-78h]
int v25; // [esp+12Ch] [ebp-74h]
int v26; // [esp+130h] [ebp-70h]
int v27; // [esp+134h] [ebp-6Ch]
int v28; // [esp+138h] [ebp-68h]
int v29; // [esp+13Ch] [ebp-64h]
int v30; // [esp+140h] [ebp-60h]
char v31; // [esp+14Fh] [ebp-51h]
char v32[17]; // [esp+178h] [ebp-28h]
char v33; // [esp+189h] [ebp-17h]
char v34; // [esp+18Ah] [ebp-16h]
char v35; // [esp+18Bh] [ebp-15h]
char v36; // [esp+18Ch] [ebp-14h]
char v37; // [esp+18Dh] [ebp-13h]
v31 = 0;
v9 = 1;
v10 = 4;
v11 = 14;
v12 = 10;
v13 = 5;
v14 = 36;
v15 = 23;
v16 = 42;
v17 = 13;
v18 = 19;
v19 = 28;
v20 = 13;
v21 = 27;
v22 = 39;
v23 = 48;
v24 = 41;
v25 = 42;
v26 = 26;
v27 = 20;
v28 = 59;
v29 = 4;
v30 = 0;
printf("please enter flag:");
while ( 1 )
{
v6 = getch();
v32[v31] = v6;
if ( !(_BYTE)v6 || v32[v31] == 13 )
break;
if ( v32[v31] == 8 )
{
printf("\b\b");
--v31;
}
else
{
printf("%c", v32[v31++]);
}
}
v8 = 0;
for ( i = 0; i < 17; ++i )
{
if ( v32[i] != byte_415768[*(&v9 + i)] )
v8 = 1;
}
if ( v33 != 49 || v34 != 48 || v35 != 50 || v36 != 52 || v37 != 125 )
v8 = 1;
v32[v31] = 0;
printf("\r\n");
if ( v8 )
{
printf("wrong\n");
main(v3, v4, v5);
}
else
{
printf("success\n");
}
system("pause");
HIDWORD(v1) = v0;
LODWORD(v1) = 0;
return v1;
}
分析函数可以得知,只有当变量V8=0时,flag才是正确的,所以我们需要满足v8=1不成立的条件,所以通过如下对于各变量的地址值,通过对各变量地址值作为所给字符串形成的字符数组的数组下标分别按计算的顺序取出,即可得到答案
首先先得到数组的值
脚本用C写的,如下
#include
#include
using namespace std;
int main()
{
string a="sKfxEeft}f{gyrYgthtyhifsjei53UUrrr_t2cdsef66246087138\0087138";
char cc[100];
strncpy(cc,a.c_str(),a.length()+1);
int num[100]={1,4,14,10,5,36,23,42,13,19,28,13,27,39,48,41,42,26,20,59,4,0};
for(int i=0;i<17;i++)
{cout<
python更简单:
a='sKfxEeft}f{gyrYgthtyhifsjei53UUrrr_t2cdsef66246087138\0087138'
b=[1,4,14,10,5,36,23,42,13,19,28,13,27,39,48,41,42,26,20,59,4,0]
for i in range(17):
print(a[b[i]],end='')
print('1024}')
运行脚本可得到:
KEY{e2s6ry3r5s8f6
此时可以发现,末尾的部分即为第二个条件不成立:
所以末尾加上'1024}'
最后得到flag:
KEY{e2s6ry3r5s8f61024}