[VC]FASM函数导入工具

来源:互联网 发布:linux时钟同步windows 编辑:程序博客网 时间:2024/05/21 13:23

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")typedefstruct _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 VApExport = (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这个信息。

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