记一次逆向工程作业(汇编windows编程)

记一次逆向工程作业(汇编windows编程)_第1张图片

(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


记一次逆向工程作业(汇编windows编程)_第2张图片

实验过程:用到的文件和功能

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中,按键也会释放下去而不是之前的勾取住,然后如图

 记一次逆向工程作业(汇编windows编程)_第3张图片

 

读取输入的字符存入文件d:\\key.txt。生成测试:

运行testhook.exe装入钩子打开notepad输入记一次逆向工程作业(汇编windows编程)_第4张图片

到D盘目录下

 记一次逆向工程作业(汇编windows编程)_第5张图片

参考一个简单的键盘钩子程序

 


你可能感兴趣的:(逆向)