Проблема с хуком на dll (64x)
26.05.2019, 13:57. Показов 1401. Ответов 0
Здравствуйте, есть такая проблема, я пытаюсь перехватить в WS2_32.dll функцию recv в своей программе 64x, но проблема в том что джамп указывает вообще в несуществующую память, и когда переходит, то выдает ошибку, так же и с другими dll. Если пробовать перехватить функцию в user32.dll, то проблем не возникает. Что делать, как фиксить?
| Delphi | 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
| unit uInvalidDialogHook;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, SpliceHelper2,Winsock, Vcl.OleCtrls, SHDocVw;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
Memo1: TMemo;
WebBrowser1: TWebBrowser;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
HotPathSpliceRec: THotPachSpliceData;
WindowList: TStringList;
function InterceptedCreateWindowExW(dwExStyle: DWORD; lpClassName: PWideChar;
lpWindowName: PWideChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall;
var
S: string;
Index: Integer;
begin
// снимаем перехват
SpliceLockJmp(HotPathSpliceRec.FuncAddr, HotPathSpliceRec.LockJmp);
try
// запоминаем информацию о созданном окне
Index := -1;
if not IsBadReadPtr(lpClassName, 1) then
begin
S := 'ClassName: ' + string(lpClassName);
S := IntToStr(WindowList.Count + 1) + ': ' + S;
Index := WindowList.Add(S);
end;
// вызываем оригинальную функцию
Result := CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle,
X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
// добавляем информацию о вызове в список
if Index >= 0 then
begin
S := S + ', handle: ' + IntToStr(Result);
WindowList[Index] := S;
end;
finally
// восстанавливаем перехват
SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE);
end;
end;
function InterceptedRecv1(s: TSocket; var Buf; len, flags: Integer): Integer;
var
d: TCopyDataStruct;
begin
SpliceLockJmp(HotPathSpliceRec.FuncAddr, HotPathSpliceRec.LockJmp);
try
WindowList.Add(IntToStr(len));
Result := recv(s, Buf, len, flags);
finally
// восстанавливаем перехват
SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.WebBrowser1.Navigate('https://ya.ru');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// инициализируем структуру для перехватчика
InitHotPatchSpliceRec('user32.dll','CreateWindowExW',
@InterceptedCreateWindowExW, HotPathSpliceRec);
InitHotPatchSpliceRec('WS2_32.dll','recv',
@InterceptedRecv1, HotPathSpliceRec);//пример с recv
// пишем прыжок в область NOP-ов
SpliceNearJmp(PAnsiChar(HotPathSpliceRec.FuncAddr) - NearJmpSpliceRecSize,
HotPathSpliceRec.SpliceRec);
// перехватываем CreateWindowExW
SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE);
try
// Создаем список в котором будет хранится информация о созданных окнах
WindowList := TStringList.Create;
try
// открываем диалог
OpenDialog1.Execute;
// по завершении отображаем полученный список
Memo1.Lines.Text := WindowList.Text;
finally
WindowList.Free;
end;
finally
// снимаем перехват
SpliceLockJmp(HotPathSpliceRec.FuncAddr, HotPathSpliceRec.LockJmp);
end;
end;
end. |
|
| Delphi | 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
| unit SpliceHelper2;
interface
uses
Windows;
const
LOCK_JMP_OPKODE: Word = $F9EB;
JMP_OPKODE: Word = $E9;
type
// структура для обычного сплайса через JMP NEAR OFFSET
TNearJmpSpliceRec = packed record
JmpOpcode: Byte;
Offset: DWORD;
end;
THotPachSpliceData = packed record
FuncAddr: FARPROC;
SpliceRec: TNearJmpSpliceRec;
LockJmp: Word;
end;
const
NearJmpSpliceRecSize = SizeOf(TNearJmpSpliceRec);
LockJmpOpcodeSize = SizeOf(Word);
procedure SpliceNearJmp(FuncAddr: Pointer; NewData: TNearJmpSpliceRec);
procedure SpliceLockJmp(FuncAddr: Pointer; NewData: Word);
procedure InitHotPatchSpliceRec(const LibraryName, FunctionName: string;
InterceptHandler: Pointer; out HotPathSpliceRec: THotPachSpliceData);
procedure InitHotPatchSpliceRecEx(const LibraryName, FunctionName: string;
InterceptHandler, Trampoline: Pointer; out HotPathSpliceRec: THotPachSpliceData);
implementation
// процедура пищет новый блок данных по адресу функции
procedure SpliceNearJmp(FuncAddr: Pointer; NewData: TNearJmpSpliceRec);
var
OldProtect: DWORD;
begin
VirtualProtect(FuncAddr, NearJmpSpliceRecSize,
PAGE_EXECUTE_READWRITE, OldProtect);
try
Move(NewData, FuncAddr^, NearJmpSpliceRecSize);
finally
VirtualProtect(FuncAddr, NearJmpSpliceRecSize,
OldProtect, OldProtect);
end;
end;
procedure ExecuteAsm(FuncAddr: Pointer; NewData: Word);
asm
push rbx
mov ax, NewData
mov rcx, FuncAddr
lock xchg word ptr [rcx], ax
pop rbx
end;
// процедура атомарно изменяет два байта по переданному адресу
procedure SpliceLockJmp(FuncAddr: Pointer; NewData: Word);
var
OldProtect: DWORD;
begin
VirtualProtect(FuncAddr, LockJmpOpcodeSize, PAGE_EXECUTE_READWRITE, OldProtect);
try
ExecuteAsm(FuncAddr,NewData);
finally
VirtualProtect(FuncAddr, LockJmpOpcodeSize, OldProtect, OldProtect);
end;
end;
// процедура инициализирует структуру для установки перехвата
procedure InitHotPatchSpliceRec(const LibraryName, FunctionName: string;
InterceptHandler: Pointer; out HotPathSpliceRec: THotPachSpliceData);
begin
// запоминаем оригинальный адрес перехватываемой функции
HotPathSpliceRec.FuncAddr :=
GetProcAddress(GetModuleHandle(PChar(LibraryName)), PChar(FunctionName));
// читаем два байта с ее начала, их мы будем перезатирать
Move(HotPathSpliceRec.FuncAddr^, HotPathSpliceRec.LockJmp, LockJmpOpcodeSize);
// инициализируем опкод JMP NEAR
HotPathSpliceRec.SpliceRec.JmpOpcode := JMP_OPKODE;
// рассчитываем адрес прыжка (поправка на NearJmpSpliceRecSize не нужна,
// т.к. адрес находится уже со смещением)
HotPathSpliceRec.SpliceRec.Offset :=
PAnsiChar(InterceptHandler) - PAnsiChar(HotPathSpliceRec.FuncAddr);
end;
// процедура инициализирует структуру для установки перехвата и подготавливает трамплин для вызова
procedure InitHotPatchSpliceRecEx(const LibraryName, FunctionName: string;
InterceptHandler, Trampoline: Pointer; out HotPathSpliceRec: THotPachSpliceData);
var
OldProtect: DWORD;
TrampolineSplice: TNearJmpSpliceRec;
begin
// запоминаем оригинальный адрес перехватываемой функции
HotPathSpliceRec.FuncAddr :=
GetProcAddress(GetModuleHandle(PChar(LibraryName)), PChar(FunctionName));
// читаем два байта с ее начала, их мы будем перезатирать
Move(HotPathSpliceRec.FuncAddr^, HotPathSpliceRec.LockJmp, LockJmpOpcodeSize);
// Подготавливаем трамплин
VirtualProtect(Trampoline, LockJmpOpcodeSize + NearJmpSpliceRecSize,
PAGE_EXECUTE_READWRITE, OldProtect);
try
Move(HotPathSpliceRec.LockJmp, Trampoline^, LockJmpOpcodeSize);
TrampolineSplice.JmpOpcode := JMP_OPKODE;
TrampolineSplice.Offset := PAnsiChar(HotPathSpliceRec.FuncAddr) -
PAnsiChar(Trampoline) - NearJmpSpliceRecSize;
Trampoline := PAnsiChar(Trampoline) + LockJmpOpcodeSize;
Move(TrampolineSplice, Trampoline^, SizeOf(TNearJmpSpliceRec));
finally
VirtualProtect(Trampoline, LockJmpOpcodeSize + NearJmpSpliceRecSize,
OldProtect, OldProtect);
end;
// инициализируем опкод JMP NEAR
HotPathSpliceRec.SpliceRec.JmpOpcode := JMP_OPKODE;
// рассчитываем адрес прыжка (поправка на NearJmpSpliceRecSize не нужна,
// т.к. адрес находится уже со смещением)
HotPathSpliceRec.SpliceRec.Offset :=
PAnsiChar(InterceptHandler) - PAnsiChar(HotPathSpliceRec.FuncAddr);
end;
end. |
|
0
|