记一次FGO逆向过程 chapter3
本帖最后由 ss22219 于 2018-3-5 16:43 编辑上一篇中通过源代码对比获取到了mono_image_open_from_data_with_name的地址
但是事情并没有那么简单,mono_image_open_from_data_with_name函数处有大量的db代码
说明这一块代码是处理过的,还原难度很大,想要获取正确的流程,就一定要调试才行
问题又回来了,干掉反调试
通过分析,在dlopen libunity之后程序就退出了,于是分析libunity的init_array段
发现有好几十个函数地址。。。。
不过看到输出窗口处有一个线程被创建了,感觉很可疑
打开debug option,设置thread start/end
发现libNetHtProtect中启动了一个线程,libNetHtProtect什么时候加载的?
查看发现libmono引用了它,linker会在libmono加载前给他分析出来
很明显,这libNetHtProtect应该是反调试的关键了
libmono是个壳,这个壳的导入会先执行libNetHtProtect,这个Protect会创建一个线程去检查是否有调试器
把libNetHtProtect创建的线程全部暂停掉,libunity成功加载
但是分析libNetHtProtect难度有点大,到这里我已经花了不少时间,已经没有耐心跟他玩了
一切加壳和加密在Dump面前都是纸老虎
——鲁迅
===========================================================
只要是解密完成了,就一定会在内存中保存有对应的文件
android中/proc/pid/maps记录了进程内存的分布
在/proc/pid/map_files中可以以文件的方式操作这些内存区域
adb shell
ps
cp /proc/2420/map_files/* ./
其中2420就是fgo的进程id,把这些文件拿出来
如何在内存中查找一个dll文件?
dll文件有DOS头,是一个标准的Nt File,我们可以通过DOS头来搜索内存中的所有dll文件
https://bbs.pediy.com/thread-223649.htm
这篇文章中给出了对应的代码,很好Copy Paste,直接运行没问题
找到了好几个dll文件,这里用dnSpy一个个试,发现有一个识别不了
emm...
https://www.perfare.net/1010.html
大香蕉这篇文章中提到如何还原文件
这里我是自己编写了个程序进行还原
程序源代码下面会给出
执行后成功用dnSpy打开
到这里就成功解密了程序文件
===========================================
FGO系列到这里还不会完结,之后还会有游戏代码的分析
这一章内容不多,但其实花了很多时间和精力,翻阅了很多文章与源码
感谢所有愿意分享的人,让我从一个逆向小白走到现在,你们的文章让我有动力继续学习下去
下一章:
https://www.52pojie.cn/thread-698513-1-1.html
上一章:
https://www.52pojie.cn/thread-697414-1-1.html 楼主,今天又出新版本了,原来的修复代码不灵了,有空看看哈 大佬,能不能把这个程序发我,谢谢。
https://bbs.pediy.com/thread-223649.htm
char * findDosHeader(char * buffer, int length, int *out_length) {
char * pe = NULL;
for (int i = 0; i < length - 0x200; i++) {
WORD * p = (WORD *)(buffer + i);
if (*p != IMAGE_DOS_SIGNATURE) {
continue;
}
IMAGE_NT_HEADERS * ntheader = (IMAGE_NT_HEADERS *)(buffer + 0x80 + i);
if (ntheader->Signature != IMAGE_NT_SIGNATURE){
continue;
}
IMAGE_FILE_HEADER * fileheader = &ntheader->FileHeader;
if (!(fileheader->Characteristics & IMAGE_FILE_DLL)){
continue;
}
IMAGE_SECTION_HEADER * section = IMAGE_FIRST_SECTION(ntheader);
int size = 0;
for (int j = 0; j < fileheader->NumberOfSections; j++) {
if ((section + j)->SizeOfRawData + (section + j)->PointerToRawData > size) {
size = (section + j)->SizeOfRawData + (section + j)->PointerToRawData;
}
}
*out_length = size;
return (buffer + i);
}
return NULL;
}
void find(const char * fileName) {
FILE *fp = NULL;
fopen_s(&fp, fileName, "rb");
if (fp == NULL) {
return;
}
fseek(fp, 0L, SEEK_END);
int length = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char * pFileBuffer = new char;
fread_s(pFileBuffer, length, 1, length, fp);
char* ppe = pFileBuffer;
int image_length = 0;
int buffer_length = length;
while (true)
{
char f;
buffer_length -= image_length;
ppe = findDosHeader(ppe + image_length, length - (ppe - pFileBuffer) - image_length, &image_length);
if (ppe != NULL) {
sprintf_s(f, "%s.%x-%x.dll", fileName, ppe, image_length);
FILE* outfp = 0;
fopen_s(&outfp, f, "wb+");
fwrite(ppe, image_length, 1, outfp);
fclose(outfp);
printf("%x %x\n", ppe, image_length);
}
else{
break;
}
}
delete[] pFileBuffer;
fclose(fp);
} 前来学习,占座 前排膜拜、学习!不知不觉就到了第三章,个人感觉即使最后不放附件能学到那么多也是值得,感谢dalao分享! 前来学习,占座 可以,学习了 学习,学习,虽然看不太懂 我现在也是小白,跟着楼主学习 鲁迅:我没说过这话 LightingZero 发表于 2018-2-12 09:52
前排膜拜、学习!不知不觉就到了第三章,个人感觉即使最后不放附件能学到那么多也是值得,感谢dalao分享!
能把我的经验传递出去才是最重要的.... 问一下dalao dump了少前找不到解密后的assemblyCsharp是因为pe结构被破坏了还是解密完就释放了?