打开torrent文件时,迅雷会对torrent文件进行解析,得到需要下载的内容,所以想要对迅雷解析torrent文件的逻辑进行尝试二进制漏洞挖掘。
经过使用procmon抓包以及逆向分析,发现迅雷对torrent文件的解析流程在动态链接库AssistantTools.dll的导出函数XL_ParseTorrentFileW中。 所以目标模块就是AssistantTools.dll,接口就是XL_ParseTorrentFileW。
(1)winafl目录在“D:__workspace__\fuzz\winafl”
(2)dynamorio目录在“D:__workspace__\fuzz\dynamorio”
注:编译winafl和dynamorio请参考这篇文章
1.源文件fuzz_program.cpp
2.编译源文件fuzz_program.cpp得到fuzz_program.exe
1、准备在目录“D:__workspace__\fuzz\test_winafl\thunder_torrent”下进行fuzz;
2、将AssistantTools.dll拷贝到目录下; (AssistantTools.dll来自“D:\softwares\Thunder Network\Thunder\Program\resources\bin\SDK\AssistantTools.dll”)
3、由于AssistantTools.dll依赖P2PBase.dll,所以也需要将P2PBase.dll拷贝到目录下; (P2PBase.dll来自“D:\softwares\Thunder Network\Thunder\Program\resources\bin\SDK\P2PBase.dll”)
4、将winafl.dll拷贝到目录下; (winafl.dll来自"D:__workspace__\fuzz\winafl\build_Win32\bin\Release\winafl.dll")
5、准备一个语料库目录samples,里面塞满各种地方找来的torrent文件;
6、最后目录下如图所示;
1、通过dynamorio工具对fuzz_program.exe在解析torrent文件时的执行流程进行污点跟踪,得到二进制的覆盖率文件,执行命令如下;
2、之后在当前目录下会看到生成的drcov前缀的log文件;
3、使用32位ida打开AssistantTools.dll,使用ida插件lighthouse打开刚才生成的log文件;
4、简单检查一下目标函数XL_ParseTorrentFileW的代码覆盖情况,绿色的为覆盖的部分;
可以看到,原本samples目录中有92个测试样本,最小化到minset目录后得到13个测试样本;
之后生成afl前缀的log文件,运行afl-fuzz.exe前设置的coverage_module参数和target_module参数的值只能从log文件中列出的模块里获取。
计划使用一个master,两个slave分别为slave01和slave02; 1、master
2、slave01
3、slave02
Ctrl+C
恢复fuzz只需要将原命令的“-i”参数修改为“-”即可,其他参数不变; 1、master
2、slave01
3、slave02
1、查看单个fuzzer的状态 以查看master的状态为例,将master状态输出到目录stat下;
在stat目录下输出的是index.html文件和三张png图片,直接拉到浏览器中查看即可;
2、查看所有fuzzer状态
输出内容会直接打印在屏幕上; 如上图所示,目前有3个fuzzer在运行,共产生了17个crash文件;
共得到两类crash;
1、除零异常导致的crash 这类样本占了大多数,一般来说很难利用,意义不大;
2、栈溢出导致的crash 别激动,经过分析,很难利用,原因如下: 在解析torrent文件的过程中,每次文件中出现一个‘d’字符,都会导致程序递归调用同一个函数,最终导致栈溢出;
我将得到的两类crash分别取出一个样本放到了附件crash.7z中; 只要双击运行crash样本文件即可触发迅雷去解析,然后就会得到如下错误提示框;
希望大家能发现更多不同类型的crash
extern "C" __declspec(dllexport) VOID fuzz_method(CHAR * filePath);
// AssistantTools.dll
static HMODULE hAssistantTools = NULL;
// AssistantTools!XL_ParseTorrentFileW
signed int __cdecl XL_ParseTorrentFileW(CHAR* aFileName, PVOID* a1);
using Fun_XL_ParseTorrentFileW = decltype(&XL_ParseTorrentFileW);
static Fun_XL_ParseTorrentFileW fun_XL_ParseTorrentFileW = NULL;
// AssistantTools!XL_ReleaseTorrentFileInfoW
void __cdecl XL_ReleaseTorrentFileInfoW(PVOID a1);
using Fun_XL_ReleaseTorrentFileInfoW = decltype(&XL_ReleaseTorrentFileInfoW);
static Fun_XL_ReleaseTorrentFileInfoW fun_XL_ReleaseTorrentFileInfoW = NULL;
VOID fuzz_method(CHAR* filePath)
{
PVOID a1 = NULL;
fun_XL_ParseTorrentFileW(filePath, &a1);
if (a1)
{
fun_XL_ReleaseTorrentFileInfoW(a1);
}
return;
}
int main(int argc, char* argv[])
{
CHAR assistantTools_path[MAX_PATH] = {0};
CHAR* pTemp = NULL;
if (2 != argc)
{
printf("Parameter Error\n");
goto End;
}
// 获取AssistantTools.dll的全路径
if(0 == GetModuleFileNameA(NULL, assistantTools_path, sizeof(assistantTools_path)))
{
printf("GetModuleFileNameA Error\n");
goto End;
}
pTemp = strrchr(assistantTools_path, '\\');
if(NULL == pTemp)
{
printf("strrchr Error\n");
goto End;
}
++pTemp;
*pTemp = '\0';
strcat(pTemp, ASSISTANTTOOLS_DLL);
// 加载AssistantTools.dll并获取函数地址
hAssistantTools = LoadLibraryA(assistantTools_path);
if (NULL == hAssistantTools)
{
printf("LoadLibraryA fail: 0x%x\n", GetLastError());
goto End;
}
fun_XL_ParseTorrentFileW = (Fun_XL_ParseTorrentFileW)GetProcAddress(hAssistantTools, "XL_ParseTorrentFileW");
if (NULL == fun_XL_ParseTorrentFileW)
{
printf("GetProcAddress fail\n");
goto End;
}
fun_XL_ReleaseTorrentFileInfoW = (Fun_XL_ReleaseTorrentFileInfoW)GetProcAddress(hAssistantTools, "XL_ReleaseTorrentFileInfoW");
if (NULL == fun_XL_ParseTorrentFileW)
{
printf("GetProcAddress fail\n");
goto End;
}
fuzz_method(argv[1]);
End:
if(hAssistantTools)
{
FreeLibrary(hAssistantTools);
}
return 0;
}
extern "C" __declspec(dllexport) VOID fuzz_method(CHAR * filePath);
// AssistantTools.dll
static HMODULE hAssistantTools = NULL;
// AssistantTools!XL_ParseTorrentFileW
signed int __cdecl XL_ParseTorrentFileW(CHAR* aFileName, PVOID* a1);
using Fun_XL_ParseTorrentFileW = decltype(&XL_ParseTorrentFileW);
static Fun_XL_ParseTorrentFileW fun_XL_ParseTorrentFileW = NULL;
// AssistantTools!XL_ReleaseTorrentFileInfoW
void __cdecl XL_ReleaseTorrentFileInfoW(PVOID a1);
using Fun_XL_ReleaseTorrentFileInfoW = decltype(&XL_ReleaseTorrentFileInfoW);
static Fun_XL_ReleaseTorrentFileInfoW fun_XL_ReleaseTorrentFileInfoW = NULL;
VOID fuzz_method(CHAR* filePath)
{
PVOID a1 = NULL;
fun_XL_ParseTorrentFileW(filePath, &a1);
if (a1)
{
fun_XL_ReleaseTorrentFileInfoW(a1);
}
return;
}
int main(int argc, char* argv[])
{
CHAR assistantTools_path[MAX_PATH] = {0};
CHAR* pTemp = NULL;
if (2 != argc)
{
printf("Parameter Error\n");
goto End;
}
// 获取AssistantTools.dll的全路径
if(0 == GetModuleFileNameA(NULL, assistantTools_path, sizeof(assistantTools_path)))
{
printf("GetModuleFileNameA Error\n");
goto End;
}
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-3-5 02:51
被TechForBad编辑
,原因:
上传的附件: