source: zzuf/trunk/src/libzzuf/sys.c @ 4813

Last change on this file since 4813 was 4813, checked in by Sam Hocevar, 8 years ago

win32: add debug information to the function diversion code.

  • Property svn:keywords set to Id
File size: 4.5 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006-2010 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  This program is free software. It comes without any warranty, to
7 *  the extent permitted by applicable law. You can redistribute it
8 *  and/or modify it under the terms of the Do What The Fuck You Want
9 *  To Public License, Version 2, as published by Sam Hocevar. See
10 *  http://sam.zoy.org/wtfpl/COPYING for more details.
11 */
12
13/*
14 *  sys.c: system-dependent initialisation
15 */
16
17#include "config.h"
18
19/* Need this for RTLD_NEXT */
20#define _GNU_SOURCE
21
22#if defined HAVE_STDINT_H
23#   include <stdint.h>
24#elif defined HAVE_INTTYPES_H
25#   include <inttypes.h>
26#endif
27
28#ifdef HAVE_DLFCN_H
29#   include <dlfcn.h>
30#endif
31
32#if defined HAVE_WINDOWS_H
33#   include <windows.h>
34#   include <imagehlp.h>
35#   include <tlhelp32.h>
36#   define import_t PIMAGE_IMPORT_DESCRIPTOR
37#   define thunk_t PIMAGE_THUNK_DATA
38#endif
39
40#include <stdio.h>
41
42#include "sys.h"
43#include "lib-load.h"
44
45#if defined HAVE_DLFCN_H
46void *_zz_dl_lib = RTLD_NEXT;
47#endif
48
49#if defined HAVE_WINDOWS_H
50static void insert_funcs(void *);
51
52/* TODO: get rid of this later */
53HINSTANCE (WINAPI *LoadLibraryA_orig)(LPCSTR);
54HINSTANCE WINAPI LoadLibraryA_new(LPCSTR path)
55{
56    return LoadLibraryA_orig(path);
57}
58
59BOOL (WINAPI *AllocConsole_orig)(void);
60BOOL WINAPI AllocConsole_new(void)
61{
62    return AllocConsole_orig();
63}
64
65BOOL (WINAPI *AttachConsole_orig)(DWORD);
66BOOL WINAPI AttachConsole_new(DWORD d)
67{
68    return AttachConsole_orig(d);
69}
70#endif
71
72void _zz_sys_init(void)
73{
74#if defined HAVE_WINDOWS_H
75    MEMORY_BASIC_INFORMATION mbi;
76    MODULEENTRY32 entry;
77    void *list;
78    int k;
79
80    /* Enumerate all loaded objects and overwrite some functions */
81    VirtualQuery(_zz_sys_init, &mbi, sizeof(mbi));
82    list = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
83    entry.dwSize = sizeof(entry);
84    for(k = Module32First(list, &entry); k; k = Module32Next(list, &entry))
85    {
86        if(entry.hModule == mbi.AllocationBase)
87            continue; /* Don't replace our own functions */
88
89        fprintf(stderr, "diverting functions from %s\n", entry.szModule);
90        insert_funcs(entry.hModule);
91    }
92    CloseHandle(list);
93#elif defined HAVE_DLFCN_H
94    /* If glibc is recent enough, we use dladdr() to get its address. This
95     * way we are sure that the symbols we load are the most recent version,
96     * or we may get weird problems. We choose fileno as a random symbol to
97     * get, because we know we don't divert it. */
98#   if HAVE_DLADDR
99    Dl_info di;
100    if (dladdr(&fileno, &di) != 0)
101    {
102        void *lib = dlopen(di.dli_fname, RTLD_NOW);
103        if (lib)
104            _zz_dl_lib = lib;
105    }
106#   endif
107#else
108    /* Nothing to do on our platform */
109#endif
110}
111
112#if defined HAVE_WINDOWS_H
113static void insert_funcs(void *module)
114{
115    static zzuf_table_t *list[] =
116    {
117        table_win32,
118    };
119
120    zzuf_table_t *diversion;
121    void *lib;
122    unsigned long dummy;
123    import_t import;
124    thunk_t thunk;
125    int k, j, i;
126
127    import = (import_t)
128        ImageDirectoryEntryToData(module, TRUE,
129                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &dummy);
130    if(!import)
131        return;
132
133    for (k = 0, diversion = NULL; k < sizeof(list) / sizeof(*list); )
134    {
135        if (!diversion)
136            diversion = list[k];
137
138        if (!diversion->lib)
139        {
140            k++;
141            diversion = NULL;
142            continue;
143        }
144
145        fprintf(stderr, "diverting method %s (from %s)\n",
146                        diversion->name, diversion->lib);
147
148        lib = GetModuleHandleA(diversion->lib);
149        *diversion->old = (void *)GetProcAddress(lib, diversion->name);
150
151        for(j = 0; import[j].Name; j++)
152        {
153            char *name = (char *)module + import[j].Name;
154            if(lstrcmpiA(name, diversion->lib) != 0)
155                continue;
156
157            thunk = (thunk_t)((char *)module + import->FirstThunk);
158            for(i = 0; thunk[i].u1.Function; i++)
159            {
160                void **func = (void **)&thunk[i].u1.Function;
161                if(*func != *diversion->old)
162                    continue;
163
164                /* FIXME: The StarCraft 2 hack uses two methods for function
165                 * diversion. See HookSsdt() and HookHotPatch(). */
166                VirtualProtect(func, sizeof(func), PAGE_EXECUTE_READWRITE, &dummy);
167                WriteProcessMemory(GetCurrentProcess(), func, &diversion->new,
168                                    sizeof(diversion->new), NULL);
169            }
170        }
171
172        diversion++;
173    }
174}
175#endif
Note: See TracBrowser for help on using the repository browser.