(1)strlen(char *s)
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include msvcrt.inc
includelib msvcrt.lib
.data
szText db "Reverse Engineering", 0
format db "length = %d", 0AH, 0
.code
main PROC
LEA EDI, szText
MOV ECX,0FFFFFFFFH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
XOR AL, AL
MOV EBX, EDI
REPNE SCASB
INC EDI
SUB EDI, EBX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE crt_printf, addr format, EDI
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP
END main
将eax置为0,用scasb,使得edi与eax的值比较,直到edi所指地址存的数据为’/0′,即为字符串结束时停止循环,此时与edi最初的位置(ebx)向减,再减去’/0’所占用的1,即为字符串长度,结果为19 。
(2)strchr(const *char s)
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include msvcrt.inc
includelib msvcrt.lib
.data
szText db "Reverse Engineering", 0
chr db 'i'
format db "%d", 0AH, 0
.code
main PROC
LEA EDI, szText
MOV ECX,0FFFFFFFFH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV EBX,EDI
MOV EAX,i
REPN SCASB
INC EBX
SUB EDI,EBX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP
END main
使用scasb,这里将chr的值给eax,当scas停止时即为chr第一次出现的位置,返回这个位置与原来位置的差值就是答案。
(3)strcmp(const *s,const *c)
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include msvcrt.inc
includelib msvcrt.lib
.data
format db "%d", 0AH, 0
szText db "Reverse Engineering", 0
szText2 db "Reverse Engineering", 0 ;szText==szText2
szText3 db "Reverse Eng", 0 ;szText>szText3
szText4 db "Reverse Engj", 0 ;szTextszText5
.code
main PROC
LEA ESI, szText
LEA EDI, szText2 ;result=0
;LEA EDI, szText3 ;result=1
;LEA EDI, szText4 ;result=-1
;LEA EDI, szText5 ;result=1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START:
XOR ECX,ECX
MOV EAX,[ESI+ECX]
MOV EBX,[EDI+ECX]
CMP EAX,EBX
JC s1
JNC s2
JZ s3
s1:
MOV EAX,1
JMP HALT
s2:
MOV EAX,-1
JMP HALT
s3:
CMP EAX,0
JZ s4
JMP START
s4:
MOV EAX,0
JMP STOP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE crt_printf, addr format, EAX
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP
END main
每次循环给ecx加1,使字符串每一位进行比较,如果前者大于后者,则跳转到s1,输出结果1,如果前者小于后者,则跳转到s2,输出-1,如果相等,则跳转到s3,判断字符是否为0,如果为0,说明字符串结束,输出结果0,如果不为0,则字符串未结束,顺移到下一位进行比较。
(4)strset(char *s,char c)
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include msvcrt.inc
includelib msvcrt.lib
.data
szText db "Reverse Engineering", 0 ;
chr db 'j' ;
.code
main PROC
LEA EDI, szText
LEA ESI, chr
MOV ECX,0FFFFFFFFH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV EBX, [ESI]
L:
MOV AX, [EDI]
CMP AL, 0
JZ STOP
MOV [EDI], BL
INC EDI
LOOP L
STOP:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INVOKE crt_printf, addr szText
INVOKE crt_getchar
INVOKE ExitProcess, 0
main ENDP
END main
实验过程:用到的文件和功能
TestHook.cpp
#include "stdio.h"
#include "conio.h"
#include "windows.h"
typedef void (*PFN_HOOKSTART)();
typedef void (*PFN_HOOKSTOP)();
void main()
{
HMODULE hDll = NULL;
PFN_HOOKSTART HookStart = NULL;
PFN_HOOKSTOP HookStop = NULL;
hDll = LoadLibraryA("HookDll.dll"); // 装载HookDll.dll
if( hDll == NULL )
return;
// 获取导出函数HookStart()和HookStop()的地址
HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, "HookStart");
HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, "HookStop");
HookStart(); //开始钩取键盘消息
// 等到用户输入'q'才终止钩取
printf("press 'q' to quit!\n");
while( _getch() != 'q' ) ;
HookStop(); //终止钩取键盘消息
FreeLibrary(hDll); //卸载HookDll.dll
}
将HookDll.dll加载到当前进程
调用HookStart()函数开始钩取
等待用户输入’q’
调用HookStop()函数终止钩取
HookDll.cpp
#include "stdio.h"
#include "windows.h"
HINSTANCE g_hInstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved){
switch( dwReason ){
case DLL_PROCESS_ATTACH:
g_hInstance = hinstDLL;
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam){
char szPath[MAX_PATH] = {0,};
char *p = NULL;
if( nCode >= 0 ) {
// bit 31 : 0 => press, 1 => release
if( !(lParam & 0x80000000) ){
GetModuleFileNameA(NULL, szPath, MAX_PATH);
p = strrchr(szPath, '\\');
//若加载当前DLL的进程的可执行文件名称为notepad.exe,则消息不会传递给下一个钩子
if( !_stricmp(p + 1, "notepad.exe") )
return 1;
}
}
// 当前进程不是notepad.exe,将消息传递给下一个钩子
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void HookStart() {
g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
}
__declspec(dllexport) void HookStop() {
if( g_hHook ) {
UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
}
#ifdef __cplusplus
}
#endif
KeyboardProc()回调函数:在键盘按键释放时,检查加载HookDll.dll的进程是否为notepad.exe,若是,则返回1;若不是,则调用CallNextHookEx(),将消息传递给应用程序或下一钩子
一:先试试testhook和hookdll,在VS中新建一个解决方案拷贝hookdll到项目下 参考VS2017动态链接库(.dll)的生成与使用 生成hookdll的解决方案,目录下找到生成的dll,再次新建一个控制台程序拷贝testhook生成exe文件,把dll拷贝并重命名为HookDll.dll放到和exe同一目录下运行exe文件检查效果,发现钩子勾取了键盘输入直到输入q结束
那现在就是主要工作修改hookdll的代码实现要求:
主要参数——KeyboardHookProc函数的各个参数意义如下:
nCode 消息的类型,有HC_ACTION
wParam 按键的状态(按下或弹起)WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP
lParam 指向KeyboardHookStruct结构的指针,该结构包含了按键的详细信息。
代码部分: 去掉return1,既当即使是在notepad中,按键也会释放下去而不是之前的勾取住,然后如图
读取输入的字符存入文件d:\\key.txt。生成测试:
到D盘目录下
参考一个简单的键盘钩子程序