[VC]FASM函数导入工具

FASM在构建输入表的时候只需要符号即可,并不像VC那样需要lib,这是FASM编译速度快的因素之一。

而FASM从官网上下载的时候,windows的函数库是不全的,连最常用的都没有,只好手动添加了。

在include\api文件夹下,稍微看一下就能搞懂格式。

一般情况下,FASM编译时是不会检查函数的参数个数的,除非在include\pcount下有相应的声明。

我就写了个给FASM导入函数的小工具,便于开发,手动一个一个写太费劲了。

函数少一些还凑合,可是系统的DLL一弄都是上百个,用的时候加一点,时间久了就烦了。

写这个工具,一劳永逸。。。。。。

-----------

思路就是用户输入DLL文件名或者路径,把这个DLL加载到内存,分析导出表,然后按照FASM的格式来整理出一份文件。

代码如下:

 Header.h

#ifndef _INCLUDE_HEADER_H_
#define _INCLUDE_HEADER_H_
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "msvcrt.lib")

typedef	struct _FUNC_LINK
{
	PCHAR      pFuncName;
	_FUNC_LINK *pNext;
}FUNC_LINK, *PFUNC_LINK;

#endif

Entry.cpp

#include "Header.h"

PFUNC_LINK g_pLink = NULL;

int main(int argc, PCHAR argv[])
{
	HANDLE hDll, hFile;
	DWORD  dwTmp, *pFuncName;
	CHAR   *pNames, szDstFile[MAX_PATH], *pDllName, szWrite[70], szTmp[30];
	PFUNC_LINK pCurrNode = NULL, pTmpNode;
	PIMAGE_EXPORT_DIRECTORY pExport;

	system("color 0a");
	printf("ExportApi tool for FASM \n"
			"This Application able to export functions from dll files\n"
			"http://blog.csdn.net/Sidyhe\n\n");
	__try
	{
		if (argc <= 1)
		{
			printf("Usage:\nExportApi.exe file.dll [or file full path]\n");
			__leave;
		}
		hDll = GetModuleHandle(argv[1]);
		if (hDll == NULL)
		{
			hDll = LoadLibraryEx(argv[1], NULL, DONT_RESOLVE_DLL_REFERENCES);
		}
		if (hDll == NULL)
		{
			printf("ERROR_INVALID_PARAMETER\n");
			__leave;
		}
		//转换一步到位,因为镜像已经加载成功了,不存在什么无效PE等问题
		pExport = (PIMAGE_EXPORT_DIRECTORY)(((PIMAGE_NT_HEADERS)
				(((PIMAGE_DOS_HEADER)hDll)->e_lfanew + (ULONG)hDll))-> \
				OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
		if (pExport == NULL)
		{
			printf("Find no export table.\n");
			__leave;
		}
		//RVA to VA
		pExport = (PIMAGE_EXPORT_DIRECTORY)((ULONG)hDll + (ULONG)pExport);
		pFuncName = (PDWORD)(pExport->AddressOfNames + (ULONG)hDll);
		//组成链表,不考虑释放了
		for (dwTmp = 0; dwTmp < pExport->NumberOfNames; dwTmp++)
		{
			pNames = (PCHAR)(pFuncName[dwTmp] + (ULONG)hDll);
			if (pCurrNode == NULL)//第一个
			{
				pCurrNode = (PFUNC_LINK)malloc(sizeof(FUNC_LINK));
				pCurrNode->pFuncName = pNames;
				pCurrNode->pNext = NULL;
				g_pLink = pCurrNode;
			}
			else
			{
				pCurrNode->pNext = (PFUNC_LINK)malloc(sizeof(FUNC_LINK));
				pCurrNode = pCurrNode->pNext;
				pCurrNode->pFuncName = pNames;
				pCurrNode->pNext = NULL;
			}
		}
		printf("Find %d Functions.\n\n", pExport->NumberOfNames);
		GetModuleFileName(NULL, szDstFile, sizeof(szDstFile));
		pNames = strrchr(argv[1], '\\');
		if (pNames)//是完整路径
		{
			lstrcpy(strrchr(szDstFile, '\\'), pNames);
			pDllName = pNames + 1;
		}
		else//只是文件名
		{
			lstrcpy(strrchr(szDstFile, '\\') + 1, argv[1]);
			pDllName = argv[1];
		}
		lstrcpy(strrchr(szDstFile, '.') + 1, "inc");
		*strrchr(pDllName, '.') = '\0';
		hFile = CreateFile(szDstFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
		{
			printf("CreateFile Error. Code:0x%08X", GetLastError());
			__leave;
		}
		//写import部分
		sprintf(szWrite, "import %s", pDllName);
		WriteFile(hFile, szWrite, lstrlen(szWrite), &dwTmp, NULL);
		for (pCurrNode = g_pLink; pCurrNode; pCurrNode = pCurrNode->pNext)
		{
			sprintf(szWrite, ", \\\r\n       %s, \'%s\'", pCurrNode->pFuncName, pCurrNode->pFuncName);
			WriteFile(hFile, szWrite, lstrlen(szWrite), &dwTmp, NULL);
		}
		//写api部分,与ANSI和UNICODE相关的
		sprintf(szWrite, "\r\n\r\napi    ");
		WriteFile(hFile, szWrite, lstrlen(szWrite), &dwTmp, NULL);
		for (pCurrNode = g_pLink; pCurrNode; pCurrNode = pCurrNode->pNext)
		{
			dwTmp = lstrlen(pCurrNode->pFuncName);
			if (pCurrNode->pFuncName[dwTmp - 1] == 'A')
			{
				//可能是ANSI函数,找UNICODE函数
				for (pTmpNode = g_pLink; pTmpNode; pTmpNode = pTmpNode->pNext)
				{
					if (pTmpNode == pCurrNode) continue;
					//SDK没有lstrcmpn???
					if(strncmp(pTmpNode->pFuncName, pCurrNode->pFuncName, dwTmp - 1) != 0) continue;
					if (pTmpNode->pFuncName[dwTmp - 1] != 'W') continue;
					lstrcpyn(szTmp, pCurrNode->pFuncName, dwTmp);
					sprintf(szWrite, "%s, \\\r\n       ", szTmp);
					WriteFile(hFile, szWrite, lstrlen(szWrite), &dwTmp, NULL);
					break;
				}
			}
		}
		//多写了一次", \"和空格
		SetFilePointer(hFile, -12, NULL, FILE_CURRENT);
		SetEndOfFile(hFile);
		//其实我真不想关,结束了什么都么了
		CloseHandle(hFile);
		printf("output:\n%s\n", szDstFile);
	}
	__finally
	{
		//没必要了,程序立马退出
//		FreeLibrary(hDll);
	}
	ExitProcess(0);
	return 0;
}

------------

此工具不适用于自己写的dll,因为不管有没有ANSI和UNICODE(A和W结尾的函数),我都会添加api这个信息。

非要使用的话就把输出后的文件自己整理一下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值