dll2cpp

来源:互联网 发布:扬州大学网络教学平台 编辑:程序博客网 时间:2024/06/08 09:06
 // 根据 dll 的输出表和 c 头文件,产生中间文件 。编译好,主要用于替换系统 dll, 监视
// 更详细的操作(windows 核心编程上有这种工具的介绍,忘记在哪张了)。
// 避免过多的 hook 问题。
// 记得有前辈写过这个工具,但是没有找到。只好发点时间自己写了, 其中还有一些问题没有解决,需要手动修改


/*
author: dummyz@126.com
*/

#pragma warning(disable : 4786)
#include <Windows.h>
#include <cstdio>
#include <ctime>
#include <cassert>
#include <list>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;

typedef vector<string> string_vector;

static int parse_cheader(const char* fname, string_vector& fun_def)
{
   ifstream ifile(fname);

   if ( !ifile )
       return 0;

   ifile.seekg(0, ios::end);
   const size_t fsize = ifile.tellg();
   ifile.seekg(0, ios::beg);
  
   auto_ptr<char> buf(new char[fsize + 1]);
   char* const _buf = buf.get();
   if ( _buf == NULL )
       return 0;
  
   ifile.read(_buf, fsize);
   ifile.close();

   _buf[fsize] = 0;
  
   bool skip1 = false;
   bool _skip1 = false;
   bool skip2 = false;
   int flag = -1;
   char* fun_name = NULL;

   for ( char* p = _buf; *p != 0; p++ )
   {
       // 跳过注释和宏
       if ( *p == '/n' )
       {
           skip1 = _skip1;
           _skip1 = false;

           p++;
       }
      
       if ( *p == '*' && p[1] == '/' )
       {
           skip2 = false;
           p += 2;
       }
      
       if ( *p == '//' && skip1 )
       {
           _skip1 = true;
       }

       if ( skip1 || skip2 )
           continue;
      
       if ( *p == '/' )
       {
           if ( p[1] == '/' )
           {
               skip1 = true;
               _skip1 = false;
           }
           else if ( p[1] == '*' )
               skip2 = true;
       }
       else if ( *p == '#' )
       {
           skip1 = true;
           _skip1 = false;
       }

       if ( skip1 || skip2 || strchr(" /t/n{}", *p) != 0 )
           continue;
      
       if ( fun_name == NULL )
       {
           fun_name = p;
           flag = -1;
       }
       else
       {
           if ( *p == ';' )
           {
               *p = 0;
               if ( flag == 0 && strncmp(fun_name, "typedef", 7) != 0 )
               {
           //       printf("%s;/n", fun_name);
                   fun_def.push_back(fun_name);
               }
               fun_name = NULL;
           }
           else if ( *p == '(' )
           {
               if ( flag == -1 )
                   flag++;
               flag++;
           }
           else if ( *p == ')' )
           {
               flag--;
           }
           else if ( strchr("/"{}", *p) != NULL )
           {
               fun_name = NULL;
           }
       }
   }

   return fun_def.size();
}

static long alig(long a, long n)
{
   long r = a % n;
   return (r == 0) ? a : (a + n) - r;
}

static long rav2raw(const void* image, long rav)
{
   PIMAGE_DOS_HEADER dosh = (PIMAGE_DOS_HEADER)image;
   PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)((char*)image + dosh->e_lfanew);
   PIMAGE_SECTION_HEADER secth = IMAGE_FIRST_SECTION(nth);

   if ( rav < secth->VirtualAddress )
       return rav;

   for ( unsigned i = 0; i < nth->FileHeader.NumberOfSections; i++ )
   {
       long a = alig(secth->VirtualAddress + secth->Misc.VirtualSize, nth->OptionalHeader.SectionAlignment);
       if ( secth->VirtualAddress <= rav && a > rav )
           return rav - secth->VirtualAddress + secth->PointerToRawData;

       secth++;
   }

   return -1;
}

static char* gen_def_fname(const char* cpp_fname, char* def_fname)
{
   strncpy(def_fname, cpp_fname, MAX_PATH);

   char* fname = strrchr(def_fname, '//');
   if ( fname == NULL )
       fname = strrchr(def_fname, '//');

   if ( fname == NULL )
       fname = def_fname;
   else
       fname++;

   char* ext = strrchr(fname, '.');
   if ( ext == NULL )
       ext = strlen(def_fname) + def_fname;

   strcpy(ext, ".def");
   return def_fname;
}

int dll2cpp(
   const char* dll_fname,
   const char* cpp_fname,
   string_vector& fun_def
   )
{
   ifstream dll_ifile(dll_fname, ios::binary);
   if ( !dll_ifile )
       return 0;
  
   ofstream cpp_ofile(cpp_fname);
   if ( !cpp_ofile )
       return 0;
  
   char def_fname[MAX_PATH];
   ofstream def_ofile(gen_def_fname(cpp_fname, def_fname));
   if ( !def_ofile )
       return 0;

   dll_ifile.seekg(0, ios::end);
   const dll_fsize = dll_ifile.tellg();
   dll_ifile.seekg(0, ios::beg);

   auto_ptr<char> ibuf(new char[dll_fsize]);
   char* const _ibuf = ibuf.get();
   if ( _ibuf == NULL )
       return 0;

   dll_ifile.read(_ibuf, dll_fsize);
   dll_ifile.close();

   PIMAGE_DOS_HEADER dosh;
   PIMAGE_NT_HEADERS nth;

   dosh = (PIMAGE_DOS_HEADER)_ibuf;
   nth = (PIMAGE_NT_HEADERS)(_ibuf + dosh->e_lfanew);
   if (
       dosh->e_magic != IMAGE_DOS_SIGNATURE ||
       nth->Signature != IMAGE_NT_SIGNATURE ||
       nth->FileHeader.NumberOfSections == 0 ||
       nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0
       )
   {
       return 0;
   }
  
   long a;

   a = rav2raw(_ibuf, nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
   if ( a == -1 )
       return 0;
   PIMAGE_EXPORT_DIRECTORY expdir = (PIMAGE_EXPORT_DIRECTORY)(_ibuf + a);

   a = rav2raw(_ibuf, expdir->AddressOfNames);
   if ( a == -1 )
       return 0;
   PDWORD fun_name_a = (PDWORD)(_ibuf + a);

   a = rav2raw(_ibuf, expdir->AddressOfNameOrdinals);
   if ( a == -1 )
       return 0;
   PWORD fun_name_ord_a = (PWORD)(_ibuf + a);
  
   time_t t = time(NULL);
   cpp_ofile <<
       "/*/nThis File Created By Dll2CPP v0.1/n" << ctime(&t) << "*//n"
       "/* Written by dummyz@126.com (2007) *//n"
       "/n/n"
       "#define _WIN32_WINNT 0x0501/n"
       "#include <windows.h>/n/n"
       "#ifndef NAKED/n"
       "#define NAKED __declspec(naked)/n"
       "#endif/n"
       "#ifdef WINBASEAPI/n"
       "#undef WINBASEAPI/n"
       "#define WINBASEAPI/n"
       "#endif/n"
       "#ifdef WINUSERAPI/n"
       "#undef WINUSERAPI/n"
       "#define WINUSERAPI/n"
       "#endif/n/n"
       "BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved)/n"
       "{/n"
       "/tswitch ( dwReason )/n"
       "/t{/n"
       "/tcase DLL_PROCESS_ATTACH: break;/n"
       "/tcase DLL_PROCESS_DETACH: break;/n"
       "/tcase DLL_THREAD_ATTACH: break;/n"
       "/tcase DLL_THREAD_DETACH: break;/n"
       "/t}/n/n"
       "/treturn TRUE;/n"
       "}/n/n" << endl;
      
   def_ofile << "EXPORTS" << endl;
   for ( unsigned i = 0, j = 0; i < expdir->NumberOfFunctions; i++ )
   {
       bool ok = false;
       char buf[200];
       const char* name = NULL;
       const char* comment = NULL;
      
       if ( strstr("lstrcmp"))
       if ( j < expdir->AddressOfNameOrdinals && fun_name_ord_a[j] == i )
       {
           char* name2 = _ibuf + rav2raw(_ibuf, fun_name_a[j]);
           const int name2_len = strlen(name2);

           for ( unsigned t = 0; t < fun_def.size(); t++ )
           {
               const string& str = fun_def[t];
               const char* p = strstr(str.c_str(), name2);
               if ( p != NULL && strchr(" /t/n", p[-1]) != NULL )
               {
                   p += name2_len;
                   if ( strchr(" /t/n(", *p) != NULL )
                   {
                       name = str.c_str();
                       break;
                   }
               }
           }
          
           if ( name == NULL )
           {
               sprintf(buf, "int WINAPI %s()", name2);
               name = buf;
               comment = "/* @这个函数没找到声明的原型 */";
           }
          
           j++;
       }
       else
       {
           sprintf(buf, "int WINAPI sub_ord%08X()", i);
           name = buf;
           comment = "/* @这个函数是由序号导出的 */";
       }
      
       if ( name != NULL )
       {
           char fun_name[200];
           for ( const char* p = strchr(name, '(') - 1, *q = NULL; p > name; p-- )
           {
               if ( q != NULL )
               {
                   if ( strchr(" /t/n", *p) != NULL )
                   {
                       int len = q - p;
                      
                       strncpy(fun_name, ++p, len);
                       fun_name[len] = 0;
                      
                       if ( comment != NULL )
                           cpp_ofile << comment << endl;
                       cpp_ofile << "/* /n";
                       cpp_ofile << name << "/n*//n";
                      
                       cpp_ofile << "NAKED int WINAPI Proxy_" << fun_name << "()/n";
                       cpp_ofile << "{/n/t __asm jmp [" << fun_name << "]/n}/n/n";
                      
                       def_ofile << "/t" << fun_name << " = " << "Proxy_" << fun_name << "/t@" << i + expdir->Base << " PRIVATE/n";
                       ok = true;
                       break;
                   }
               }
               else if ( strchr(" /t/n", *p) == NULL )
               {
                   q = p;
               }
           }
       }
      
       if ( !ok )
           cout << "ERROR : " << i + expdir->Base << endl << name << endl;
   }
  
   return 0;
}

int main(int argc, char* argv[])
{
   string_vector fun_def;

   parse_cheader("D://PSDK//Include//winuser.h", fun_def);
   parse_cheader("D://PSDK//Include//winbase.h", fun_def);
   parse_cheader("D://PSDK//Include//WinCon.h", fun_def);
   parse_cheader("D://PSDK//Include//WinNls.h", fun_def);
   parse_cheader("D://PSDK//Include//WinNt.h", fun_def);
   parse_cheader("D://PSDK//Include//LZExpand.h", fun_def);
   parse_cheader("D://PSDK//Include//TlHelp32.h", fun_def);

   dll2cpp("c://windows//system32//kernel32.dll", "c://1.cpp", fun_def);

   return 0;
}
原创粉丝点击