调试加壳后Exe生成的Dump文件

之前处理外网崩溃最头痛的时莫过于拿到了崩溃的Dump但是VS对他无从下手,主要原因是加壳之后exe生成的Dump无法与未加壳的exe匹配,进而对不上符号文件,不能在源码级别调试。

直接汇编级调试Dump根据调用栈地址来判断具体调用的是哪个函数也是个方法,但来来回回跳转几层之后真是有点力不从心哇,下面给大家分享一段解决方案。

之前百度这个问题的时候看到这么一段内容:

VS调试Dump时是通过ModuleName、SizeOfImage、CheckSum、TimeDateStamp这四个属性进行匹配的,四项全部匹配才认为Exe与Dump是配套的

那么简单来说,哪怕Dump与Exe不配套,我们把这四个属性改成一一对应的,那岂不是可以强制匹配调试了?

对于PE文件而言,这四个属性很好弄。ModuleName就是文件名——XXX.exe或者XXX.dll。参者PE文件结构,TimeDateStamp在IMAGE_FILE_HEADER中、SizeOfImageI和CheckSum在MAGE_OPTIONAL_HEADER32中,对应着取出来就好。

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;  // 目标字段1
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER

typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //
    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;
 
    //
    // NT additional fields.
    //
    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;  // 目标字段2
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;     // 目标字段3
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

复杂的是Dump文件的结构,好不容易在一本软件调试的书里翻到一些内容。

Dump文件头是MINIDUMP_HEADER结构,_MINIDUMP_HEADER::NumberOfStreams表示Dump中Streams的个数,别的我们不关心我们只要找到StreamType为ModuleListStream的Stream就好。

typedef struct _MINIDUMP_HEADER {
    ULONG32 Signature;
    ULONG32 Version;
    ULONG32 NumberOfStreams;
    RVA StreamDirectoryRva;
    ULONG32 CheckSum;
    union {
        ULONG32 Reserved;
        ULONG32 TimeDateStamp;
    };
    ULONG64 Flags;
} MINIDUMP_HEADER, *PMINIDUMP_HEADER;

_MINIDUMP_HEADER::StreamDirectoryRva指向MINIDUMP_DIRECTORY*类型的数组,其长度就是_MINIDUMP_HEADER::NumberOfStreams。

遍历_MINIDUMP_HEADER::StreamDirectoryRva,找到_MINIDUMP_DIRECTORY::StreamType为ModuleListStream的那一项。

//
// The MINIDUMP_HEADER field StreamDirectoryRva points to 
// an array of MINIDUMP_DIRECTORY structures.
//
typedef struct _MINIDUMP_DIRECTORY {
    ULONG32 StreamType;
    MINIDUMP_LOCATION_DESCRIPTOR Location;
} MINIDUMP_DIRECTORY, *PMINIDUMP_DIRECTORY;

_MINIDUMP_DIRECTORY::Location记录着当前类型的Stream的位置及长度,读取数据段,强转为MINIDUMP_MODULE_LIST*类型。

_MINIDUMP_MODULE_LIST::NumberOfModules记录着Dump加载的所有模块的数量,模块的信息作为数组储存在_MINIDUMP_MODULE_LIST::Modules中,我们要修改的是exe的信息,一般来说不用去遍历_MINIDUMP_MODULE_LIST::Modules了,第一个元素就是。

//
// The minidump module list is a container for modules.
//
typedef struct _MINIDUMP_MODULE_LIST {
    ULONG32 NumberOfModules;
    MINIDUMP_MODULE Modules [ 0 ];  // 已加载模块
} MINIDUMP_MODULE_LIST, *PMINIDUMP_MODULE_LIST;

//
// The MINIDUMP_MODULE contains information about a
// a specific module. It includes the CheckSum and
// the TimeDateStamp for the module so the module
// can be reloaded during the analysis phase.
//
 
typedef struct _MINIDUMP_MODULE {
    ULONG64 BaseOfImage;
    ULONG32 SizeOfImage;    // 目标字段2
    ULONG32 CheckSum;       // 目标字段3
    ULONG32 TimeDateStamp;  // 目标字段1
    RVA ModuleNameRva;
    VS_FIXEDFILEINFO VersionInfo;
    MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
    MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
    ULONG64 Reserved0;                          // Reserved for future use.
    ULONG64 Reserved1;                          // Reserved for future use.
} MINIDUMP_MODULE, *PMINIDUMP_MODULE;

取出_MINIDUMP_MODULE_LIST::Modules[0],对应着上面取出来的Exe的信息把_MINIDUMP_MODULE::SizeOfImage、_MINIDUMP_MODULE::CheckSum、_MINIDUMP_MODULE::TimeDateStamp修改掉然后保存。

然后愉快的双击Dump按下调试,开始愉快的源码级调试吧~

题外话:改Dump的时候各类指针乱飞,最方便的做法是加载整个Dump进内存,就不用管部分加载计算偏移的事了,但是对于动辄800M+的游戏Dump文件,还要做批量修改,还是老老实实部分加载吧。

P.S. 如果崩溃点在你加壳代码混淆的部分内,放弃调试Dump吧,你啥也看不到 ╮(╯▽╰)╭。

搬运自toonyxm.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容