DLL hijacking involves manipulating a program to load a DLL that contains the desired code. We will use a simple technique here for ilustration: DLL replacement. We will build a DLL that perserve the same functionlity and interface of original DLL. So we can swap the original DLL with a the one built by us that contains additional code.
Assuming the vulnerable program has dependency on
zlib1.dll
, which is the open source library. We can
first check the version from file properties and download the
corresponding version of source code for example
zlib v1.2.1.
Execute cd
into source source folder and then execute
nmake -f win32/Makefile.msc
, we will obtain
zlib.lib,
zlib1.res.
We can now build our zlib1.dll
. Put our source code
zlib1.c with
additional instantiation logic and copy zlib.lib
,
zlib1.res
,
zlib.def
into the same folder and then execute following commands
cl /c /nologo /O2 /MD /utf-8 zlib1.c
link /NOLOGO /RELEASE /DEF:zlib.def /DLL /IMPLIB:zdll.lib /OUT:zlib1.dll zlib1.obj zlib.lib zlib1.res User32.lib Gdi32.lib
In case we don’t have module-definition or .def
file
then we will need to modify the source code of our proxy DLL
zlib1.c
. We need to first execute
dumpbin /EXPORTS zlib1.dll
so we will obtain the
export table of original zlib1.dll
. The output should
be something similar to following:
1 0 00001000 adler32
2 1 000011E0 compress
3 2 00001130 compress2
4 3 00001200 compressBound
5 4 00001510 crc32
6 5 00001760 deflate
7 6 00001680 deflateBound
8 7 00001C60 deflateCopy
9 8 00001BA0 deflateEnd
10 9 00003050 deflateInit2_
11 A 00003280 deflateInit_
12 B 00002CC0 deflateParams
13 C 00001640 deflatePrime
14 D 00002C20 deflateReset
15 E 00001530 deflateSetDictionary
16 F 00001220 get_crc_table
17 10 00003B20 gzclearerr
18 11 000039D0 gzclose
19 12 00003DC0 gzdopen
20 13 00003930 gzeof
21 14 00003A20 gzerror
22 15 00003880 gzflush
23 16 000040B0 gzgetc
24 17 000040E0 gzgets
25 18 00003DA0 gzopen
26 19 000036C0 gzprintf
27 1A 00003740 gzputc
28 1B 00003770 gzputs
29 1C 00003E00 gzread
30 1D 000038C0 gzrewind
31 1E 00004140 gzseek
32 1F 000032B0 gzsetparams
33 20 000042E0 gztell
34 21 000035A0 gzungetc
35 22 000035F0 gzwrite
36 23 00005950 inflate
37 24 000043C0 inflateBack
38 25 00005240 inflateBackEnd
39 26 00004300 inflateBackInit_
40 27 00007060 inflateCopy
41 28 00006DB0 inflateEnd
42 29 00005740 inflateInit2_
43 2A 00005810 inflateInit_
44 2B 000056F0 inflateReset
45 2C 00006E00 inflateSetDictionary
46 2D 00006F30 inflateSync
47 2E 00007030 inflateSyncPoint
48 2F 00009050 uncompress
49 30 00009120 zError
50 31 00009110 zlibCompileFlags
51 32 00009100 zlibVersion
for every export attribute we will need a add a line to our
zlib1.c
#pragma comment(linker, "/export:_<export attribute>")
for example
#pragma comment(linker, "/export:_zlibVersion")
We place generated zlib1.dll
into program directory
and replace the original one, our logic will be executed when
program try to load zlib1.dll
.
Alternatively for any other DLL even it is not open source, we can build a proxy DLL that redirect all the calls to original DLL file. There are automatic tool for generating the proxy DLL.
Reference
- API Interception via DLL Redirection
- HackTricks: Dll Hijacking
- Can we export a function made available through a static library
- creating dll with cl and linker
- /MD, /MT, /LD (Use Run-Time Library)
- Compiler options listed alphabetically
- Exporting from a DLL Using DEF Files
- /DEF (Specify Module-Definition File)
- c++ creating a window from a dll
- Create your Proxy DLLs automatically
- ProxiFy - Automatic Proxy DLL Generation
- SharpDllProxy
- DLL代理转发