Author:kalrey
The way is not original,but code really write by me.
Reference:http://hi.baidu.com/robin_dev/blog/item/5a593fca5449ec18be09e6cf.html
Thanks.
I package the class,That is simple.
Class declare:
code:
//file:SDTShadowRestore.h
#ifndef SDTSHADOWRESTORE_H
#define SDTSHADOWRESTORE_H
#include <windows.h>
#include <Tchar.h>
typedef struct _SYSTEM_SERVICE_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID KiServiceTabe;
PVOID W32pServiceTable;
PVOID Reserved_1;
PVOID Reserved_2;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
class SDTShadowRestore
{
public:
SDTShadowRestore(void)
{
m_dwWin32kBase = 0;
m_dwW32pServiceTable = 0;
m_KeServiceDescriptorTableShadow = 0;
this->Init();
}
~SDTShadowRestore(void)
{
if(m_pKernelName)
{
::GlobalFree(m_pKernelName);
}
}
bool Init(); //
DWORD FindW32pServiceTable(); //get original W32pServiceTable's memory address
DWORD GetAddressSSDTShadow(); //get KeServiceDescriptorTableShadow'smemory address in kernel
DWORD GetServiceAddressById(DWORD ServiceId); //Get Service's original Address
private:
void AnsiToPTSTR(PTSTR DesStr, char *SourceStr, DWORD cbDesStr);
DWORD GetProcFromIAT(LPCTSTR szProcName); //find function's address at Iat by function's name
private:
PIMAGE_OPTIONAL_HEADER m_pWin32kOptionalHeader; //OptionalHeader,non RVA
HMODULE m_hWin32kModule; //Win32k.sys kernel module handle load by oneself LPTSTR m_pKernelName; //kernel module
HMODULE m_hKernelModule; //ntoskrnl.exe or ntkrnlpa.exe module
DWORD m_dwKernelBase; //kernel base address
DWORD m_dwWin32kBase; //Win32k.sys base address
PSERVICE_DESCRIPTOR_TABLE m_KeServiceDescriptorTableShadow; //in kernel SSDT Shadow really memory address
DWORD m_dwW32pServiceTable; //original W32pServiceTaable really address
};
#endif
#ifndef SDTSHADOWRESTORE_H
#define SDTSHADOWRESTORE_H
#include <windows.h>
#include <Tchar.h>
typedef struct _SYSTEM_SERVICE_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID KiServiceTabe;
PVOID W32pServiceTable;
PVOID Reserved_1;
PVOID Reserved_2;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
class SDTShadowRestore
{
public:
SDTShadowRestore(void)
{
m_dwWin32kBase = 0;
m_dwW32pServiceTable = 0;
m_KeServiceDescriptorTableShadow = 0;
this->Init();
}
~SDTShadowRestore(void)
{
if(m_pKernelName)
{
::GlobalFree(m_pKernelName);
}
}
bool Init(); //
DWORD FindW32pServiceTable(); //get original W32pServiceTable's memory address
DWORD GetAddressSSDTShadow(); //get KeServiceDescriptorTableShadow'smemory address in kernel
DWORD GetServiceAddressById(DWORD ServiceId); //Get Service's original Address
private:
void AnsiToPTSTR(PTSTR DesStr, char *SourceStr, DWORD cbDesStr);
DWORD GetProcFromIAT(LPCTSTR szProcName); //find function's address at Iat by function's name
private:
PIMAGE_OPTIONAL_HEADER m_pWin32kOptionalHeader; //OptionalHeader,non RVA
HMODULE m_hWin32kModule; //Win32k.sys kernel module handle load by oneself LPTSTR m_pKernelName; //kernel module
HMODULE m_hKernelModule; //ntoskrnl.exe or ntkrnlpa.exe module
DWORD m_dwKernelBase; //kernel base address
DWORD m_dwWin32kBase; //Win32k.sys base address
PSERVICE_DESCRIPTOR_TABLE m_KeServiceDescriptorTableShadow; //in kernel SSDT Shadow really memory address
DWORD m_dwW32pServiceTable; //original W32pServiceTaable really address
};
#endif
Class implements:
#include "SDTShadowRestore.h"
typedef struct _SYSTEM_MODULE_INFORMATION // Information Class 11
{
ULONG Reserved[2]; //+0
PVOID Base; //+08h
ULONG Size; //+0ch
ULONG Flags; //+10h
USHORT Index; //+14h
USHORT Unknown; //+16h
USHORT LoadCount; //+18h
USHORT ModuleNameOffset; //+1Ah
CHAR ImageName[256]; //+1Ch
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _tagSysModuleList
{
ULONG ulCount;
SYSTEM_MODULE_INFORMATION smi;
} SYSMODULELIST, *PSYSMODULELIST;
typedef DWORD SYSTEM_INFORMATION_CLASS;
#define STATUS_INFO_LEN_MISMATCH 0xc0000004
typedef LONG (_stdcall *pFnZwQuerySystemInformation )
( IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength );
void SDTShadowRestore::AnsiToPTSTR(PTSTR DesStr, char *SourceStr, DWORD cbDesStr)
{
#ifndef _UNICODE
lstrcpy(DesStr, SourceStr);
#else
MultiByteToWideChar(CP_ACP, 0, SourceStr, -1, DesStr, cbDesStr);
#endif
}
bool SDTShadowRestore::Init()
{
pFnZwQuerySystemInformation ZwQuerySystemInformation = (pFnZwQuerySystemInformation)::GetProcAddress(::LoadLibrary(_T("ntdll.dll")), "ZwQuerySystemInformation");
PSYSMODULELIST pSysModuleList = NULL;
DWORD ReturnLength = 0, dwRet = 0;
TCHAR ModuleName[MAX_PATH];
dwRet = ZwQuerySystemInformation(11, (PVOID)pSysModuleList, 0, &ReturnLength);
if(dwRet == STATUS_INFO_LEN_MISMATCH)
{
pSysModuleList = (PSYSMODULELIST)::GlobalAlloc(GPTR, ReturnLength);
ZwQuerySystemInformation(11, (PVOID)pSysModuleList, ReturnLength, NULL); //获取系统加载模块信息
PSYSTEM_MODULE_INFORMATION pSystemModuleInformation = &(pSysModuleList->smi);
m_dwKernelBase = (DWORD)(pSystemModuleInformation->Base); //获取系统内核核心模块ntoskrnl.exe加载基址,PAE模式为ntkrnlpa.exe
char* pAnsiKernelName = pSystemModuleInformation->ModuleNameOffset + pSystemModuleInformation->ImageName;
m_pKernelName = (PTSTR)::GlobalAlloc(GPTR, sizeof(TCHAR)*(strlen(pAnsiKernelName)+1));
this->AnsiToPTSTR(m_pKernelName, pAnsiKernelName, sizeof(TCHAR)*(strlen(pAnsiKernelName)+1)); //获取内核核心模块名称(以此判定是否为PAE模式)
this->m_hKernelModule = ::LoadLibraryEx(m_pKernelName, 0, DONT_RESOLVE_DLL_REFERENCES); //在用户态加载内核核心模块
this->m_hWin32kModule = ::LoadLibraryEx(_T("Win32k.sys"), 0, DONT_RESOLVE_DLL_REFERENCES); //在用户态加载Win32k.sys模块
for(DWORD index = 0; index < pSysModuleList->ulCount; index++) //通过循环获取Win32k.sys在内核加载的基址,后面重定位Shadow SSDT中函数地址用到
{
TCHAR szModuleName[50];
AnsiToPTSTR(szModuleName, (pSystemModuleInformation->ImageName + pSystemModuleInformation->ModuleNameOffset), 50);
if(lstrcmp(_tcsupr(szModuleName), _T("WIN32K.SYS")) == 0)
{
this->m_dwWin32kBase = (DWORD)(pSystemModuleInformation->Base);
break;
}
pSystemModuleInformation++;
}
if(pSysModuleList)
{
::GlobalFree(pSysModuleList);
}
}
this->m_pWin32kOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)m_hWin32kModule + ((PIMAGE_DOS_HEADER)m_hWin32kModule)->e_lfanew + 0x18); //Win32k.sys可选头
return true;
}
DWORD SDTShadowRestore::GetAddressSSDTShadow() //得到KeServiceDescriptorTableShadow在内核中的内存地址
{
if(m_dwWin32kBase)
{
DWORD dwKeAddSystemServiceTable = (DWORD)GetProcAddress(m_hKernelModule, "KeAddSystemServiceTable");
for(DWORD dwCurAddress = dwKeAddSystemServiceTable; dwCurAddress < dwKeAddSystemServiceTable + 0x100; dwCurAddress++)
{
/*通过定位
8d8840355580 lea ecx,nt!KeServiceDescriptorTableShadow (80553540)[eax]
833900 cmp dword ptr [ecx],0
*/
if(*(PWORD)dwCurAddress == 0x888d && *(PWORD)(dwCurAddress + 6) == 0x3983)
{
m_KeServiceDescriptorTableShadow = (PSERVICE_DESCRIPTOR_TABLE)(*(PDWORD)(dwCurAddress + 2) - (DWORD)m_hKernelModule + m_dwKernelBase);
return (DWORD)m_KeServiceDescriptorTableShadow; //该地址位于内核空间不可访问
}
}
}
return NULL;
}
DWORD SDTShadowRestore::FindW32pServiceTable() //得到原始W32pServiceTable内存地址
{
//获取Win32k.sys得DriverEntry地址
DWORD dwEntryPoint = this->m_pWin32kOptionalHeader->AddressOfEntryPoint + (DWORD)m_hWin32kModule;
//从IAT中获取KeAddSystemServiceTable的地址
DWORD dwKeAddSystemServiceTable = GetProcFromIAT(_T("KeAddSystemServiceTable"));
/*IDA反汇编结果:
68 80 A2 99 BF push offset off_BF99A280
FF 15 58 D4 98 BF call ds:KeAddSystemServiceTable
*/
//通过call ds:KeAddSystemServiceTable的定位,该定位应该比较准确
for(DWORD dwCurAddress = dwEntryPoint; dwCurAddress < dwEntryPoint + 0x1000; dwCurAddress++)
{
if(*(PWORD)dwCurAddress == 0x15ff )
{
//计算出加载后的ds:KeAddSystemServiceTable地址,然后该地址中存放的即是KeAddSystemServiceTable真实入口地址
DWORD dwFunAddress = *(PDWORD)(*(PULONG)(dwCurAddress + 2) - m_pWin32kOptionalHeader->ImageBase + (DWORD)m_hWin32kModule);
if(dwKeAddSystemServiceTable == dwFunAddress)
{
//将该地址结合内核中Win32k的加载地址进行重定位
m_dwW32pServiceTable = *(PDWORD)(dwCurAddress - 4) - m_pWin32kOptionalHeader->ImageBase + (DWORD)m_hWin32kModule;
return m_dwW32pServiceTable;
}
}
}
return 0;
}
DWORD SDTShadowRestore::GetServiceAddressById(DWORD ServiceId) //获取服务原始地址
{
if(!m_dwW32pServiceTable)
{
FindW32pServiceTable();
}
if(m_dwW32pServiceTable)
{
return *(PDWORD)(m_dwW32pServiceTable + ServiceId * 4) - m_pWin32kOptionalHeader->ImageBase + m_dwWin32kBase;
}
}
DWORD SDTShadowRestore::GetProcFromIAT(LPCTSTR szProcName) //根据函数名在IAT中查找函数地址
{
PIMAGE_IMPORT_DESCRIPTOR pImageTable = (PIMAGE_IMPORT_DESCRIPTOR)(m_pWin32kOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + (DWORD)m_hWin32kModule);
TCHAR szDllName[20];
while(pImageTable->Name || pImageTable->FirstThunk || pImageTable->OriginalFirstThunk)
{
AnsiToPTSTR(szDllName, (char*)(pImageTable->Name + (DWORD)m_hWin32kModule), 20);
if(lstrcmp(_tcsupr(szDllName), _T("NTOSKRNL.EXE")) == 0)
{
break;
}
pImageTable++;
}
PIMAGE_THUNK_DATA pOrgFirstThunk = (PIMAGE_THUNK_DATA)(pImageTable->OriginalFirstThunk + (DWORD)m_hWin32kModule);
PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)(pImageTable->FirstThunk + (DWORD)m_hWin32kModule);
TCHAR szFunName[30];
for(DWORD index = 0; &(pOrgFirstThunk[index]); index++)
{
if(!(pOrgFirstThunk[index].u1.Ordinal & IMAGE_ORDINAL_FLAG32 ))
{
PIMAGE_IMPORT_BY_NAME pFunName = (PIMAGE_IMPORT_BY_NAME)(pOrgFirstThunk[index].u1.ForwarderString + (DWORD)m_hWin32kModule);
AnsiToPTSTR(szFunName, (char*)(pFunName->Name), 30);
if(lstrcmp(szFunName, szProcName) == 0)
{
return pFirstThunk[index].u1.Function;
}
}
}
return 0;
}
ShadowSSDT position use hard code
typedef struct _SYSTEM_MODULE_INFORMATION // Information Class 11
{
ULONG Reserved[2]; //+0
PVOID Base; //+08h
ULONG Size; //+0ch
ULONG Flags; //+10h
USHORT Index; //+14h
USHORT Unknown; //+16h
USHORT LoadCount; //+18h
USHORT ModuleNameOffset; //+1Ah
CHAR ImageName[256]; //+1Ch
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _tagSysModuleList
{
ULONG ulCount;
SYSTEM_MODULE_INFORMATION smi;
} SYSMODULELIST, *PSYSMODULELIST;
typedef DWORD SYSTEM_INFORMATION_CLASS;
#define STATUS_INFO_LEN_MISMATCH 0xc0000004
typedef LONG (_stdcall *pFnZwQuerySystemInformation )
( IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength );
void SDTShadowRestore::AnsiToPTSTR(PTSTR DesStr, char *SourceStr, DWORD cbDesStr)
{
#ifndef _UNICODE
lstrcpy(DesStr, SourceStr);
#else
MultiByteToWideChar(CP_ACP, 0, SourceStr, -1, DesStr, cbDesStr);
#endif
}
bool SDTShadowRestore::Init()
{
pFnZwQuerySystemInformation ZwQuerySystemInformation = (pFnZwQuerySystemInformation)::GetProcAddress(::LoadLibrary(_T("ntdll.dll")), "ZwQuerySystemInformation");
PSYSMODULELIST pSysModuleList = NULL;
DWORD ReturnLength = 0, dwRet = 0;
TCHAR ModuleName[MAX_PATH];
dwRet = ZwQuerySystemInformation(11, (PVOID)pSysModuleList, 0, &ReturnLength);
if(dwRet == STATUS_INFO_LEN_MISMATCH)
{
pSysModuleList = (PSYSMODULELIST)::GlobalAlloc(GPTR, ReturnLength);
ZwQuerySystemInformation(11, (PVOID)pSysModuleList, ReturnLength, NULL); //获取系统加载模块信息
PSYSTEM_MODULE_INFORMATION pSystemModuleInformation = &(pSysModuleList->smi);
m_dwKernelBase = (DWORD)(pSystemModuleInformation->Base); //获取系统内核核心模块ntoskrnl.exe加载基址,PAE模式为ntkrnlpa.exe
char* pAnsiKernelName = pSystemModuleInformation->ModuleNameOffset + pSystemModuleInformation->ImageName;
m_pKernelName = (PTSTR)::GlobalAlloc(GPTR, sizeof(TCHAR)*(strlen(pAnsiKernelName)+1));
this->AnsiToPTSTR(m_pKernelName, pAnsiKernelName, sizeof(TCHAR)*(strlen(pAnsiKernelName)+1)); //获取内核核心模块名称(以此判定是否为PAE模式)
this->m_hKernelModule = ::LoadLibraryEx(m_pKernelName, 0, DONT_RESOLVE_DLL_REFERENCES); //在用户态加载内核核心模块
this->m_hWin32kModule = ::LoadLibraryEx(_T("Win32k.sys"), 0, DONT_RESOLVE_DLL_REFERENCES); //在用户态加载Win32k.sys模块
for(DWORD index = 0; index < pSysModuleList->ulCount; index++) //通过循环获取Win32k.sys在内核加载的基址,后面重定位Shadow SSDT中函数地址用到
{
TCHAR szModuleName[50];
AnsiToPTSTR(szModuleName, (pSystemModuleInformation->ImageName + pSystemModuleInformation->ModuleNameOffset), 50);
if(lstrcmp(_tcsupr(szModuleName), _T("WIN32K.SYS")) == 0)
{
this->m_dwWin32kBase = (DWORD)(pSystemModuleInformation->Base);
break;
}
pSystemModuleInformation++;
}
if(pSysModuleList)
{
::GlobalFree(pSysModuleList);
}
}
this->m_pWin32kOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)m_hWin32kModule + ((PIMAGE_DOS_HEADER)m_hWin32kModule)->e_lfanew + 0x18); //Win32k.sys可选头
return true;
}
DWORD SDTShadowRestore::GetAddressSSDTShadow() //得到KeServiceDescriptorTableShadow在内核中的内存地址
{
if(m_dwWin32kBase)
{
DWORD dwKeAddSystemServiceTable = (DWORD)GetProcAddress(m_hKernelModule, "KeAddSystemServiceTable");
for(DWORD dwCurAddress = dwKeAddSystemServiceTable; dwCurAddress < dwKeAddSystemServiceTable + 0x100; dwCurAddress++)
{
/*通过定位
8d8840355580 lea ecx,nt!KeServiceDescriptorTableShadow (80553540)[eax]
833900 cmp dword ptr [ecx],0
*/
if(*(PWORD)dwCurAddress == 0x888d && *(PWORD)(dwCurAddress + 6) == 0x3983)
{
m_KeServiceDescriptorTableShadow = (PSERVICE_DESCRIPTOR_TABLE)(*(PDWORD)(dwCurAddress + 2) - (DWORD)m_hKernelModule + m_dwKernelBase);
return (DWORD)m_KeServiceDescriptorTableShadow; //该地址位于内核空间不可访问
}
}
}
return NULL;
}
DWORD SDTShadowRestore::FindW32pServiceTable() //得到原始W32pServiceTable内存地址
{
//获取Win32k.sys得DriverEntry地址
DWORD dwEntryPoint = this->m_pWin32kOptionalHeader->AddressOfEntryPoint + (DWORD)m_hWin32kModule;
//从IAT中获取KeAddSystemServiceTable的地址
DWORD dwKeAddSystemServiceTable = GetProcFromIAT(_T("KeAddSystemServiceTable"));
/*IDA反汇编结果:
68 80 A2 99 BF push offset off_BF99A280
FF 15 58 D4 98 BF call ds:KeAddSystemServiceTable
*/
//通过call ds:KeAddSystemServiceTable的定位,该定位应该比较准确
for(DWORD dwCurAddress = dwEntryPoint; dwCurAddress < dwEntryPoint + 0x1000; dwCurAddress++)
{
if(*(PWORD)dwCurAddress == 0x15ff )
{
//计算出加载后的ds:KeAddSystemServiceTable地址,然后该地址中存放的即是KeAddSystemServiceTable真实入口地址
DWORD dwFunAddress = *(PDWORD)(*(PULONG)(dwCurAddress + 2) - m_pWin32kOptionalHeader->ImageBase + (DWORD)m_hWin32kModule);
if(dwKeAddSystemServiceTable == dwFunAddress)
{
//将该地址结合内核中Win32k的加载地址进行重定位
m_dwW32pServiceTable = *(PDWORD)(dwCurAddress - 4) - m_pWin32kOptionalHeader->ImageBase + (DWORD)m_hWin32kModule;
return m_dwW32pServiceTable;
}
}
}
return 0;
}
DWORD SDTShadowRestore::GetServiceAddressById(DWORD ServiceId) //获取服务原始地址
{
if(!m_dwW32pServiceTable)
{
FindW32pServiceTable();
}
if(m_dwW32pServiceTable)
{
return *(PDWORD)(m_dwW32pServiceTable + ServiceId * 4) - m_pWin32kOptionalHeader->ImageBase + m_dwWin32kBase;
}
}
DWORD SDTShadowRestore::GetProcFromIAT(LPCTSTR szProcName) //根据函数名在IAT中查找函数地址
{
PIMAGE_IMPORT_DESCRIPTOR pImageTable = (PIMAGE_IMPORT_DESCRIPTOR)(m_pWin32kOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + (DWORD)m_hWin32kModule);
TCHAR szDllName[20];
while(pImageTable->Name || pImageTable->FirstThunk || pImageTable->OriginalFirstThunk)
{
AnsiToPTSTR(szDllName, (char*)(pImageTable->Name + (DWORD)m_hWin32kModule), 20);
if(lstrcmp(_tcsupr(szDllName), _T("NTOSKRNL.EXE")) == 0)
{
break;
}
pImageTable++;
}
PIMAGE_THUNK_DATA pOrgFirstThunk = (PIMAGE_THUNK_DATA)(pImageTable->OriginalFirstThunk + (DWORD)m_hWin32kModule);
PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)(pImageTable->FirstThunk + (DWORD)m_hWin32kModule);
TCHAR szFunName[30];
for(DWORD index = 0; &(pOrgFirstThunk[index]); index++)
{
if(!(pOrgFirstThunk[index].u1.Ordinal & IMAGE_ORDINAL_FLAG32 ))
{
PIMAGE_IMPORT_BY_NAME pFunName = (PIMAGE_IMPORT_BY_NAME)(pOrgFirstThunk[index].u1.ForwarderString + (DWORD)m_hWin32kModule);
AnsiToPTSTR(szFunName, (char*)(pFunName->Name), 30);
if(lstrcmp(szFunName, szProcName) == 0)
{
return pFirstThunk[index].u1.Function;
}
}
}
return 0;
}
ShadowSSDT position use hard code
We can find function' name to copy it by IDA.XP SP2 use 667,I write a little software to analysis function's name:
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
CHAR SrcFileName[MAX_PATH],DesFileName[MAX_PATH];
cout << "please input the file name of src:" <<endl;
cin >> SrcFileName;
cout << "please input the file name of des:" <<endl;
cin >> DesFileName;
HANDLE hSrcFile = ::CreateFileA(SrcFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(!hSrcFile)
{
return 1;
}
HANDLE hSrcMap = ::CreateFileMappingA(hSrcFile, NULL, PAGE_READONLY, 0, 0, NULL);
if(!hSrcMap)
{
return 1;
}
LPVOID lpSrcMapAddress = ::MapViewOfFile(hSrcMap, FILE_MAP_READ, 0, 0, 0);
char* pSrc = (char*)lpSrcMapAddress;
HANDLE hDesFile = ::CreateFileA(DesFileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileSizeHigh = 0;
DWORD dwFileSizeLow = ::GetFileSize(hSrcFile, &dwFileSizeHigh);
HANDLE hDesMap = ::CreateFileMappingA(hDesFile, NULL, PAGE_READWRITE, dwFileSizeHigh, dwFileSizeLow, NULL);
DWORD a = ::GetLastError();
LPVOID lpDesMapAddress = ::MapViewOfFile(hDesMap, FILE_MAP_WRITE, 0, 0, 0);
char* pDes = (char*)lpDesMapAddress;
bool bFlag = false;
while(pSrc - lpSrcMapAddress < dwFileSizeLow )
{
//加上*(pSrc - 1) == ' '(此处不是空,是空格字符)是为了防止对此类中间存在'_'符号的错误解析,_NtGdiHT_Get8BPPFormatPalette@16
if(*pSrc == '_' && *(pSrc - 1) == ' ')
{
bFlag = true;
*pDes = 'L';
pDes++;
*pDes = '"';
pDes++;
}
else if(*pSrc == '@')
{
bFlag = false;
*pDes = '"';
pDes++;
*pDes = ',';
pDes++;
*pDes = 13;
pDes++;
*pDes = 10;
pDes++;
}
else
{
if(bFlag)
{
*pDes = *pSrc;
pDes++;
}
}
pSrc++;
}
::UnmapViewOfFile(lpSrcMapAddress);
::UnmapViewOfFile(lpDesMapAddress);
::CloseHandle(hSrcMap);
::CloseHandle(hDesMap);
::CloseHandle(hSrcFile);
::CloseHandle(hDesFile);
return 0;
}
Hope to be useful for pleople in need.
#include <iostream>
using namespace std;
int main()
{
CHAR SrcFileName[MAX_PATH],DesFileName[MAX_PATH];
cout << "please input the file name of src:" <<endl;
cin >> SrcFileName;
cout << "please input the file name of des:" <<endl;
cin >> DesFileName;
HANDLE hSrcFile = ::CreateFileA(SrcFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(!hSrcFile)
{
return 1;
}
HANDLE hSrcMap = ::CreateFileMappingA(hSrcFile, NULL, PAGE_READONLY, 0, 0, NULL);
if(!hSrcMap)
{
return 1;
}
LPVOID lpSrcMapAddress = ::MapViewOfFile(hSrcMap, FILE_MAP_READ, 0, 0, 0);
char* pSrc = (char*)lpSrcMapAddress;
HANDLE hDesFile = ::CreateFileA(DesFileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileSizeHigh = 0;
DWORD dwFileSizeLow = ::GetFileSize(hSrcFile, &dwFileSizeHigh);
HANDLE hDesMap = ::CreateFileMappingA(hDesFile, NULL, PAGE_READWRITE, dwFileSizeHigh, dwFileSizeLow, NULL);
DWORD a = ::GetLastError();
LPVOID lpDesMapAddress = ::MapViewOfFile(hDesMap, FILE_MAP_WRITE, 0, 0, 0);
char* pDes = (char*)lpDesMapAddress;
bool bFlag = false;
while(pSrc - lpSrcMapAddress < dwFileSizeLow )
{
//加上*(pSrc - 1) == ' '(此处不是空,是空格字符)是为了防止对此类中间存在'_'符号的错误解析,_NtGdiHT_Get8BPPFormatPalette@16
if(*pSrc == '_' && *(pSrc - 1) == ' ')
{
bFlag = true;
*pDes = 'L';
pDes++;
*pDes = '"';
pDes++;
}
else if(*pSrc == '@')
{
bFlag = false;
*pDes = '"';
pDes++;
*pDes = ',';
pDes++;
*pDes = 13;
pDes++;
*pDes = 10;
pDes++;
}
else
{
if(bFlag)
{
*pDes = *pSrc;
pDes++;
}
}
pSrc++;
}
::UnmapViewOfFile(lpSrcMapAddress);
::UnmapViewOfFile(lpDesMapAddress);
::CloseHandle(hSrcMap);
::CloseHandle(hDesMap);
::CloseHandle(hSrcFile);
::CloseHandle(hDesFile);
return 0;
}
Hope to be useful for pleople in need.
No comments:
Post a Comment