首页
社区
课程
招聘
[原创]根据 dll 的输出表和声明文件,产生中间文件
发表于: 2007-8-26 19:21 11725

[原创]根据 dll 的输出表和声明文件,产生中间文件

dummy 活跃值
23
2007-8-26 19:21
11725
// 根据 dll 的输出表和 c 头文件,产生中间文件 。编译好,主要用于替换系统 dll, 监视
// 更详细的操作(windows 核心编程上有这种工具的介绍,忘记在哪张了)。
// 避免过多的 hook 问题。

// 记得有前辈写过这个工具,但是没有找到。只好发点时间自己写了, 其中还有一些问题没有解决,需要手动修改
// 如果谁有那个版本的工具,给个链接 谢谢了



#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 ( 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);
	dll2cpp("c:\\windows\\system32\\kernel32.dll", "c:\\1.cpp", fun_def);

	return 0;
}





[课程]Linux pwn 探索篇!

收藏
免费 7
支持
分享
最新回复 (10)
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
2
dummy的文章比这里其他人的(除了dwing)都要有创意和好
2007-8-26 19:42
0
雪    币: 272
活跃值: (143)
能力值: ( LV15,RANK:930 )
在线值:
发帖
回帖
粉丝
3
哈哈。
2007-8-26 20:52
0
雪    币: 8209
活跃值: (4458)
能力值: ( LV15,RANK:2459 )
在线值:
发帖
回帖
粉丝
4
很好,很强大
2007-8-26 21:55
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
5
大强很好很好
2007-8-27 01:56
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好强哈....很有用的东西
2007-8-27 02:32
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
7
好象是yonsm写过一个工具;)
2007-8-27 09:15
0
雪    币: 272
活跃值: (143)
能力值: ( LV15,RANK:930 )
在线值:
发帖
回帖
粉丝
8
发现很多解析头文件的 BUG
等稳定了在重新发一个版本吧
2007-8-27 14:15
0
雪    币: 272
活跃值: (143)
能力值: ( LV15,RANK:930 )
在线值:
发帖
回帖
粉丝
9
基本,好像,差不多,应该是。。。
没有问题了
2007-8-27 14:26
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
研究下再评论,不过顶还是要顶,支持下~
2007-9-2 19:01
0
雪    币: 212
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
希望 dummy 能加QQ 519415832

有事情找你谈 :)
2007-9-3 13:37
0
游客
登录 | 注册 方可回帖
返回
//