1.拿到文件,一共有48个exe应用程序文件,将其中一个用IDA打开,找到主函数:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
char ArgList[16]; // [esp+0h] [ebp-24h] BYREF
__int128 v5; // [esp+10h] [ebp-14h]
*(_OWORD *)ArgList = 0i64;
v5 = 0i64;
sub_FF12D0();
if ( sub_FF1050() )
{
sub_FF1510(
(wchar_t *)L"What is the password?\n",
*(_DWORD *)ArgList,
*(_DWORD *)&ArgList[4],
*(_DWORD *)&ArgList[8],
*(_DWORD *)&ArgList[12],
(_QWORD)v5,
*((_QWORD *)&v5 + 1));
sub_FF14C0((wchar_t *)L"%15ls", ArgList, 16);
if ( sub_FF1240(ArgList) )
{
sub_FF10B0();
if ( sub_FF1100() )
{
sub_FF1510((wchar_t *)L"Everything is awesome!\n");
sub_FF1510((wchar_t *)L"%s => %s\n", &unk_FF43A0, &unk_FF43C0);
result = (unsigned __int16)word_FF43CA;
}
else
{
sub_FF1510((wchar_t *)L"Oh look a rainbow.\n");
result = -1;
}
}
else
{
sub_FF1510((wchar_t *)L"Go step on a brick!\n");
result = -1;
}
}
else
{
sub_FF1510((wchar_t *)L"I super hate you right now.\n");
result = -1;
}
return result;
}
这个主函数是动调一遍之后得到的,动调之后主函数的内容会显示的更多一点(不清楚是什么原因)。
2.查看sub_FF1240函数:
wcscmp函数判断输入的值与word_FF4380的值是否相等。
3.查看sub_FF1050函数中的sub_FF1000函数:
发现这些利用的是资源,最后需要输入密码,才能成功执行exe文件。
4.将其中一个exe应用程序文件用16进制编辑器,然后在终端输入的最后一个字符串中找到密码:
所以密码为ZImIT7DyCMOeF6
5.执行一下:
释放的资源是一个png图片,然后这个w应该就是flag的第一位。
6.接下来比较简单了,可以按上面的步骤把48个应用程序都操作一遍,可以得到flag,也可以写脚本先提取出所有的密码,然后一一对应应用程序执行,在运行结果中直接可以得到flag。
(1)先提取应用程序中的密码:
import os
files = os.listdir(r"C:\Users\admin\Desktop\FLEGGO") #48个应用程序名
for filename in files:
filename = r"C:\Users\admin\Desktop\FLEGGO\\" + filename
with open(filename,"rb") as f: #以读的方式打开二进制文件
f=f.read()[0x2ab0:0x2ad0] #读取密码那两行十六进制数据
f=f.split(b'\x00') #去掉f对象结尾的0x00
print("\"",end="") #每一行开头输出一个"
for i in f:
if i == b'':
break
print(chr(int().from_bytes(i,byteorder='big', signed=True)),end="")
# int.from_bytes(bytes, byteorder, *, signed=False)将字节值交换为 int 值
print("\"") #每一行结尾输出一个"
运行之后得到:
(2) 每个密码对应一个应用程序,并执行应用程序:
key=["ZImIT7DyCMOeF6",
"PylRCpDK",
"UvCG4jaaIc4315",
"uVmH96JGdPkEBfd",
"3nEiXqMnXG",
"Q9WdIAGjUKdNxr6",
"UkuAJxmt8",
"b1VRfMTNPu",
"qNb6tr7n",
"KSL8EAnlIZin1gG",
"uLKEIRAEn",
"7kcuVMWeIBFGWfJ",
"NcMkqwelbRu",
"yu7hNshnpM4Vy",
"5xj9HmHyhF",
"ZYNGeumv6QuI7",
"dRnTVwZPjf0U",
"dPVLAQ8LwmhH",
"J1kj42jZsC9",
"rXZE7pDx3",
"eoneTNuryZ3eF",
"jZAorSlICuQa0g8",
"hqpNm7VJL",
"45psrewIRS",
"2LUmPSYdxDcil",
"aGUwVeVZ2c19mgE",
"goTZP4go",
"9aIZjTerf0",
"jZRmFmeIchneGS",
"Z8VCO7XbKUk",
"14bm9pHvbufOA",
"9eDMpbMSEeZ",
"auDB6HtMv",
"C446Zdun",
"nLSGJ2BdwC",
"0d7qdvEhYGc",
"5O2godXTZePdWZd",
"ohj5W6Goli",
"4z0gAyKdk",
"r6ZWNWeFadW",
"dEDDxJaxc1R",
"HQG0By9q",
"0rhvT5GX",
"Fs3Ogu6W3qk59kZ",
"8V9AzigUcb2J",
"gNbeYAjn",
"8Etmc0DAF8Qv",
"XgkvZJKe"]
import os
import subprocess
files = os.listdir("C:\\Users\admin\Desktop\FLEGGO")
i=0
for filename in files:
filename = "C:\\Users\admin\Desktop\FLEGGO\\" + filename
p = subprocess.Popen([filename], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.write(key[i].encode())
p.stdin.close()
i+=1
out=p.stdout.read()
p.stdout.close()
print (out)
其中subprocess 模块:
subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。
Popen 对象方法
- poll(): 检查进程是否终止,如果终止返回 returncode,否则返回 None。
- wait(timeout): 等待子进程终止。
- communicate(input,timeout): 和子进程交互,发送和读取数据。
- send_signal(singnal): 发送信号到子进程 。
- terminate(): 停止子进程,也就是发送SIGTERM信号到子进程。
- kill(): 杀死子进程。发送 SIGKILL 信号到子进程。
import time
import subprocess
def cmd(command):
subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8")
subp.wait(2)
if subp.poll() == 0:
print(subp.communicate()[1])
else:
print("失败")
cmd("java -version")
cmd("exit 1")
输出结果如下:
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)
失败
执行代码后,文件中多了48张png图片:
在python的运行结果中得到flag:
flag{wmmre_o3e_mcpm@emsa.tafw4on_she_r_l003_0saaunosn@flare-on.com}