Record a Reverse Engineering Job (Assemble windows Programming)

(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

Set eax to 0 and use scasb to compare the value of edi with that of eax until the data stored at the address specified by edi is'/0', that is, stop the loop at the end of the string, then subtract from the original position of edi (ebx) and subtract the 1 occupied by'/0', that is, the length of the string, the result is 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

With scasb, the value of chr is given to eax. When scas stops, it is the position where chr first appears. Returning the difference between this position and the original position is the answer.

(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      ;szText<szText4
szText5    db  "Reverse Engh", 0      ;szText>szText5
.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

If the former is larger than the latter, then jump to s1, output result 1, if the former is smaller than the latter, then jump to s2, output-1, if equal, then jump to s3, judge whether the character is 0, if 0, that means the end of the string, output result 0, if not 0, then the string does not end, move forward to the next bit. Row comparison.

(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



Experimentation: Documents and Functions Used

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"); // Loading HookDll.dll
    if( hDll == NULL )
        return;

    // Get the addresses of the derived functions HookStart() and HookStop()
	HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, "HookStart");
	HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, "HookStop");

	HookStart(); //Start hooking keyboard messages

    // Wait until the user enters'q'to terminate the hook
	printf("press 'q' to quit!\n");
	while( _getch() != 'q' )	;

	HookStop(); //Termination of hook fetching keyboard messages

	FreeLibrary(hDll); //Unload HookDll.dll
}


Load HookDll.dll to the current process

Call the HookStart() function to start hooking

Waiting for the user to enter'q'

Call the HookStop() function to terminate hooking

  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, '\\');
            //If the executable file name of the process loading the current DLL is notepad.exe, the message will not be passed to the next hook.
			if( !_stricmp(p + 1, "notepad.exe") )
				return 1;
		}
	}
    // The current process is not notepad.exe, passing messages to the next hook
	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() callback function: When the keyboard key is released, check whether the process loading HookDll.dll is notepad.exe, if it is, return 1; if not, call CallNextHookEx() to pass the message to the application or the next hook.

First: try testhook and hookdll first, and create a new solution in VS to copy hookdll for reference under the project. Generation and Use of VS2017 Dynamic Link Library (.dll) The solution of generating hookdll is to find the generated DLL in the directory, create a new console program to copy the testhook to generate exe file, rename the DLL copy and rename it HookDll.dll to run the EXE file in the same directory as exe to check the effect. It is found that the hook ticks the keyboard input until the end of the q input.

 

Now that's the main work of modifying hookdll's code implementation requirements:

The main parameters of Keyboard HookProc function are as follows:

 

nCode. Type of message, HC_ACTION

 

The status of keys (press or pop up) WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP

 

lParam: A pointer to the Keyboard HookStruct structure, which contains key details.

 

Code section: Remove return 1, even in notepad, the keys will be released instead of the previous hook, and then as shown in Figure 1

 

 

Read the input characters and store them in the file d:\key.txt. Generate test:

Run testhook.exe to load the hook and open notepad input

To the D-disk catalog

 

Reference resources A simple keyboard hook program

 

Keywords: Windows

Added by ugh82 on Sun, 19 May 2019 05:16:02 +0300