exe程序,运行后提示输入密码,输入错误退出程序,无壳,ida分析
main函数逻辑清晰,读取输入,对输入进行变表base64编码,验证编码结果
之前遇到过变表base64的题目,见REVERSE-PRACTICE-BUUCTF-7或REVERSE-PRACTICE-BUUCTF-10或base64原理及其编解码的python实现
这道题用一个工具,加密解密小玩具,来解,非常方便
elf文件,无壳,ida分析
main函数,获取输入,检验输入长度是否为10且均为0~4的数字,先后经过先序遍历和中序遍历改变输入中各个字符的位置,再顺序地放入数独“#”位置,最后检验数独
sub_400758函数和sub_400807函数先后经过先序遍历和中序遍历改变输入中各个字符的位置,本人一直想不通,于是动调,当输入为0123456789时,sub_400807函数调用结束后的v7为7381940526,于是可以知道输入中字符位置变换的规律
变换前的下标:0 1 2 3 4 5 6 7 8 9
变换后的下标:7 3 8 1 9 4 0 5 2 6
再解数独,在sub_400917函数中可知为5x5的数独
写代码换成正确的位置即可得到flag
由于输入长度只有10位,且均为0~4的数字,也可以写脚本爆破得到flag
elf文件,无壳,ida分析
main函数,读取输入,检验输入长度是否为32,有一段SMC,自修改代码
ida静态分析,先写idapython脚本完成smc
smc执行前,地址0x402219处是一大段数据
smc的idapython脚本
from idaapi import *
from idautils import *
start_addr = 0x402219
key = 0x99
for i in range(start_addr,start_addr+224):
PatchByte(i,Byte(i)^key)
smc执行完成后,按c转换成代码
在地址0x402219处右键->Edit function,将函数结束地址修改为retn指令所在地址,完成后F5反汇编
用插件Findcrypt发现sub_402219是对输入的AES加密,密钥为unk_603170,密文为res
远程调试elf,得到密钥unk_603170
写AES解密脚本即可得到flag
exe程序,运行后提示输入string,无壳,ida分析
main函数,分析可知是vm的题目,dword_403040中的数据作为opcode传入vm_operad函数中
进入vm_operad函数,分析可知
opcode为10时,读取输入,长度为15
opcode为1时,v4被赋值
opcode为7时,v4和下一个opcode比较,于是7后面的opcode为密文
其余的opcode为input的相关运算
int __cdecl vm_operad(int *opcode, int a2)
{
int result; // eax
char input[100]; // [esp+13h] [ebp-E5h]
char v4[100]; // [esp+77h] [ebp-81h]
char v5; // [esp+DBh] [ebp-1Dh]
int v6; // [esp+DCh] [ebp-1Ch]
int v7; // [esp+E0h] [ebp-18h]
int v8; // [esp+E4h] [ebp-14h]
int v9; // [esp+E8h] [ebp-10h]
int opcode_index; // [esp+ECh] [ebp-Ch]
opcode_index = 0;
v9 = 0;
v8 = 0;
v7 = 0;
v6 = 0;
while ( 1 )
{
result = opcode_index;
if ( opcode_index >= a2 )
return result;
switch ( opcode[opcode_index] )
{
case 1: // 每当opcode为1时,v4被赋值
v4[v7] = v5;
++opcode_index;
++v7;
++v9;
break;
case 2: // 每当opcode为2时,v5被赋值为下一个opcode与input的和
v5 = opcode[opcode_index + 1] + input[v9];// 由于运算使用了下一个opcode,所以opcode_index加2
opcode_index += 2;
break;
case 3:
v5 = input[v9] - LOBYTE(opcode[opcode_index + 1]);// 每当opcode为3时,v5被赋值为input与下一个opcode的差
opcode_index += 2; // 由于运算使用了下一个opcode,所以opcode_index加2
break;
case 4:
v5 = opcode[opcode_index + 1] ^ input[v9];// 每当opcode为4时,v5被赋值为input与下一个opcode异或的值
opcode_index += 2; // 由于运算使用了下一个opcode,所以opcode_index加2
break;
case 5:
v5 = opcode[opcode_index + 1] * input[v9];// 每当opcode为5时,v5被赋值为input与下一个opcode乘积的值
opcode_index += 2; // 由于运算使用了下一个opcode,所以opcode_index加2
break;
case 6: // 每当opcode为6时,跳到下一个opcode
++opcode_index;
break;
case 7: // 每当opcode为7时,验证v4和下一个opcode是否相等,意味着opcode等于7的下一个opcode为密文
if ( v4[v8] != opcode[opcode_index + 1] )
{
printf("what a shame...");
exit(0);
}
++v8;
opcode_index += 2; // 由于验证使用了下一个opcode,所以opcode_index加2
break;
case 8: // 每当opcode为8时,input的值修改
input[v6] = v5;
++opcode_index;
++v6;
break;
case 10: // opcode的第一个值为10,所以先读取输入,长度为15
read(input);
++opcode_index;
break;
case 11: // 每当opcode为11时,v5被赋值为input与数字1的差
v5 = input[v9] - 1;
++opcode_index;
break;
case 12: // 每当opcode为12时,v5被赋值为input与数字1的和
v5 = input[v9] + 1;
++opcode_index;
break;
default:
continue;
}
}
}
提取出114个opcode,手动进行分类,并按照操作码得到input[0~14]的变换过程
写逆运算脚本即可得到flag
此题目也可以用angr一把梭