修改静态库
0) 背景
有个静态库叫做 slib.lib, 其中包含两个 obj 文件:
expofunc1.obj |- void sayHello1() { printf("Hello 1\n"); } |- void sayWorld1() {} expofunc2.obj |- void sayHello2() { printf("Hello 2\n"); }
修改 sayHello1, 使输出无效 -- 即不会打印出 "Hello 1"。
一 拆分静态库成obj
1) 把 static lib 拆成 obj:
[cmd]>lib /list slib.lib >slib.txt
生成文本 : slib.txt:
Microsoft (R) Library Manager Version 9.00.21022.08 Copyright (C) Microsoft Corporation. All rights reserved. .\Debug\stdafx.obj .\Debug\expoFunc1.obj .\Debug\expoFunc2.obj
2) 编辑文本 slib.txt:
lib slib.lib /EXTRACT:.\Debug\expoFunc1.obj
lib slib.lib /EXTRACT:.\Debug\expoFunc2.obj
3) 修改 slib.txt 为 slib.bat
4) 执行 slib.bat
从 slib.lib 里提取出:
expofunc1.obj
expofunc2.obj
查看 expofunc1.obj 涉及到的符号:
dumpbin expofunc1.obj /symbols
二 关注obj
5) dump oxpofunc1.obj
dumpbin expofunc1.obj /all > expofunc1_DMP.txt
打开 expofunc1_DMP.txt, 搜索 "sayHello1", 结构如下:
SECTION HEADER #31 .text name 0 physical address 0 virtual address 49 size of raw data 4CFD file pointer to raw data (00004CFD to 00004D45) 4D46 file pointer to relocation table 0 file pointer to line numbers 4 number of relocations 0 number of line numbers 60501020 flags Code COMDAT; sym= "void __cdecl sayHello1(void)" (?sayHello1@@YAXXZ) 16 byte align Execute Read RAW DATA #31 00000000: 55 8B EC 81 EC C0 00 00 00 53 56 57 8D BD 40 FF U.ì.ìà...SVW.?@? 00000010: FF FF B9 30 00 00 00 B8 CC CC CC CC F3 AB 8B F4 ??10...?ììììó?.? 00000020: 68 00 00 00 00 FF 15 00 00 00 00 83 C4 04 3B F4 h....?......?.;? 00000030: E8 00 00 00 00 5F 5E 5B 81 C4 C0 00 00 00 3B EC è...._^[.?à...;ì 00000040: E8 00 00 00 00 8B E5 5D C3 è.....?]? RELOCATIONS #31 Symbol Symbol Offset Type Applied To Index Name -------- ---------------- ----------------- -------- ------ 00000021 DIR32 00000000 CB ??_C@_08LDIBCFKO@Hello?51?6?$AA@ (`string') 00000027 DIR32 00000000 C7 __imp__printf 00000031 REL32 00000000 CC __RTC_CheckEsp 00000041 REL32 00000000 CC __RTC_CheckEsp
这里每个函数对应一个 SECTION.
这里 sayHello1 处于 SECTION HEADER #31, 看一下 RELOCATIONS #31, 这里是 SECTION HEADER #31 引用的符号, 由于没有到 link 阶段, 所以这些符号的地址未知.
00000027 DIR32 00000000 C7 __imp__printf // 表示 RAW DATA #31 段的offset 0x27 部分引用了 __imp__printf,
// 看一下 RAW DATA #31: 00000020: 68 00 00 00 00 FF 15 00 00 00 00 83 C4 04 3B F4 h....?......?.;? ^^^^^^^^^^^ 这 4 个byte 就应该是 __imp__printf 的地址, 在 link 阶段当 __imp__printf 地址确定下来, __imp__printf 的真实地址会填充 00 00 00 00 "FF 15" 是 call 指令的机器码, 如果要让 __imp__printf 无效, 直接跳过这个函数就行, (__imp__printf 是 __cdel call, 不用管 stack 的平衡), 把 "FF 15" 修改成为 "EB 04" 即可。"EB 04" 是向前 jmp 4 byte 的机器码, 这个可以直接跳到 call __imp__printf 下一条指令.
三 修改obj
使用 notepad++ 的 HEX-Editor 插件
四 把修改后的的 obj 重新打包成静态库
[cmd]>lib /OUT:slib.lib expofunc1.obj expofunc2.obj
生成 slib.lib 就是被修改后的静态库.