-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathsample_ApiHijackImports_hook.cpp
165 lines (138 loc) · 4.31 KB
/
sample_ApiHijackImports_hook.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
Ìîäèôèêàöèÿ òàáëèö èìïîðòà/ýêñïîðòà
Âåñü API, äîñòóïíûé èç êàêîãî-ëèáî ìîäóëÿ, îïèñàí â òàê íàçûâàåìîé òàáëèöå ýêñïîðòà ýòîãî ìîäóëÿ. Ñ äðóãîé ñòîðîíû, ñïèñîê API, íåîáõîäèìûé äëÿ íîðìàëüíîé ðàáîòû îïÿòü-òàêè, ëþáîãî ìîäóëÿ, íàõîäèòñÿ â åãî òàáëèöå èìïîðòà.
Êîä âûçîâà ïðîöåäóðû èç äðóãîãî ìîäóëÿ âûãëÿäèò ïðèìåðíî òàê:
call dword ptr [__imp__MessageBeep@4 (004404cc)]
È, åñëè èçìåíèòü çíà÷åíèå ïî ýòîìó àäðåñó, ìîæíî ïîäìåíèòü îðèãèíàëüíóþ ôóíêöèþ ñâîåé. Äëÿ ýòîãî íàì ïîíàäîáèòñÿ:
Îòûñêàòü òàáëèöó èìïîðòà ôóíêöèé äëÿ íóæíîãî íàì ìîäóëÿ
Îòûñêàòü òàì óêàçàòåëü íà ïåðåõâàòûâàåìóþ ôóíêöèþ
Ñíÿòü ñ ýòîãî ó÷àñòêà ïàìÿòè àòðèáóò ReadOnly
Çàïèñàòü óêàçàòåëü íà íàøó ôóíêöèþ
Âåðíóòü çàùèòó îáðàòíî
*/
#include "stdafx.h"
#include "MainDlg.h"
HRESULT WriteProtectedMemory(LPVOID pDest, LPCVOID pSrc, DWORD dwSize)
{
// Make it writable
DWORD dwOldProtect = 0;
if (::VirtualProtect(pDest, dwSize, PAGE_READWRITE, &dwOldProtect))
{
::MoveMemory(pDest, pSrc, dwSize);
// Restore protection
::VirtualProtect(pDest, dwSize, dwOldProtect, &dwOldProtect);
return S_OK;
}
return HRESULT_FROM_WIN32(GetLastError());
}
HRESULT ApiHijackImports(
HMODULE hModule,
LPSTR szVictim,
LPSTR szEntry,
LPVOID pHijacker,
LPVOID *ppOrig
)
{
// Check args
if (::IsBadStringPtrA(szVictim, -1) ||
(!IS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) ||
::IsBadCodePtr(FARPROC(pHijacker)))
{
return E_INVALIDARG;
}
PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule);
if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ||
IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
{
return E_INVALIDARG;
}
PIMAGE_NT_HEADERS pNTHeaders =
MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew);
if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) ||
IMAGE_NT_SIGNATURE != pNTHeaders->Signature)
{
return E_INVALIDARG;
}
HRESULT hr = E_UNEXPECTED;
// Locate the victim
IMAGE_DATA_DIRECTORY& impDir =
pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR pImpDesc =
MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress),
pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1;
while(pImpDesc < pEnd)
{
if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim))
{
if (0 == pImpDesc->OriginalFirstThunk)
{
// no import names table
return E_UNEXPECTED;
}
// Locate the entry
PIMAGE_THUNK_DATA pNamesTable =
MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk);
if (IS_INTRESOURCE(szEntry))
{
// By ordinal
while(pNamesTable->u1.AddressOfData)
{
if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) &&
WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal))
{
hr = S_OK;
break;
}
pNamesTable++;
}
}
else
{
// By name
while(pNamesTable->u1.AddressOfData)
{
if (!IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal))
{
PIMAGE_IMPORT_BY_NAME pName = MakePtr(PIMAGE_IMPORT_BY_NAME,
hModule, pNamesTable->u1.AddressOfData);
if (0 == ::lstrcmpiA(LPSTR(pName->Name), szEntry))
{
hr = S_OK;
break;
}
}
pNamesTable++;
}
}
if (SUCCEEDED(hr))
{
// Get address
LPVOID *pProc = MakePtr(LPVOID *, pNamesTable,
pImpDesc->FirstThunk - pImpDesc->OriginalFirstThunk);
// Save original handler
if (ppOrig)
*ppOrig = *pProc;
// write to write-protected memory
return WriteProtectedMemory(pProc, &pHijacker, sizeof(LPVOID));
}
break;
}
pImpDesc++;
}
return hr;
}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
LPVOID pOldHandler = NULL;
HRESULT hr = ApiHijackImports(::GetModuleHandle(NULL), "USER32.dll", "MessageBeep", MyMessageBeep, &pOldHandler);
if (SUCCEEDED(hr))
{
// Our handler will be used instead of MessageBeep()
::MessageBeep(m_uType);
// Restore old handler
ApiHijackImports(::GetModuleHandle(NULL), "USER32.dll", "MessageBeep", pOldHandler, NULL);
}
else
MessageBox(_T("Failed to hijack ::MessageBeep() imports"), NULL, MB_OK | MB_ICONHAND);
return 0;
}