在开源工程中, 看到类似下面的代码很蛋疼.

 

ReLoadNtosCALL((PVOID)(&RObReferenceObjectByHandle),L"ObReferenceObjectByHandle",g_ulSystemKernelModuleBase,(ULONG)g_pImageModuleBase);
	ReLoadNtosCALL((PVOID)(&RKeInitializeEvent),L"KeInitializeEvent",g_ulSystemKernelModuleBase,(ULONG)g_pImageModuleBase);
	ReLoadNtosCALL((PVOID)(&RIoAllocateIrp),L"IoAllocateIrp",g_ulSystemKernelModuleBase,(ULONG)g_pImageModuleBase);
	ReLoadNtosCALL((PVOID)(&RIoCallDriver),L"IoCallDriver",g_ulSystemKernelModuleBase,(ULONG)g_pImageModuleBase);
	ReLoadNtosCALL((PVOID)(&RKeWaitForSingleObject),L"KeWaitForSingleObject",g_ulSystemKernelModuleBase,(ULONG)g_pImageModuleBase);


如果是一句就算了,关键是铺天盖地的都是.

该函数的后两个参数是全局的, 由于原版没有加 g_ 来标记,改的时候,花了一些时间.

如果是用宏来写, 那只需要改该宏的定义.

 

这是内核重载用的, 进了一个自己的函数, 如果要用到内核API, 都要用自己重载的那份.

所以在工程中,到处都是 ReLoadNtosCALL函数.

经过观察, 这句代码只有前2个参数是不同的,且有关联性。

如果搞成一个宏, 会使工程的可读性,可维护性提高.

 

做了一个试验, 验证了宏的写法, 用.cod文件做了验证,宏写的正确.

// testMicro.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>

/// 测试字符串和变量名有关联时, 如何定义一个合适的宏, 简化输入

/// _tcscpy(szMsg, L"Msg");
#define MY_PRINT(x) _tcscpy(sz##x, L#x);

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t szMsg1[_MAX_PATH];

    // _tcscpy(szMsg, L"Msg");
    MY_PRINT(Msg1)

    _tprintf(L"%s\r\n", szMsg1);

    getwchar();
	return 0;
}


在VS2010IDE, 设置列表文件输出.

打开 testMicro.cod , 查看 testMicro.cpp 编译产生的内容, 看是自己是否将宏写对了?

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01 

	TITLE	D:\LsTemp\test\testMicro\testMicro.cpp
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC	??_C@_19EEPNDKNE@?$AA?$CF?$AAs?$AA?$AN?$AA?6?$AA?$AA@ ; `string'
PUBLIC	??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@	; `string'
PUBLIC	__$ArrayPad$
PUBLIC	_wmain
EXTRN	__imp__getwchar:PROC
EXTRN	__imp__wprintf:PROC
EXTRN	__imp__wcscpy:PROC
EXTRN	___security_cookie:DWORD
EXTRN	@__security_check_cookie@4:PROC
EXTRN	@_RTC_CheckStackVars@8:PROC
EXTRN	__RTC_CheckEsp:PROC
EXTRN	__RTC_Shutdown:PROC
EXTRN	__RTC_InitBase:PROC
;	COMDAT ??_C@_19EEPNDKNE@?$AA?$CF?$AAs?$AA?$AN?$AA?6?$AA?$AA@
; File d:\lstemp\test\testmicro\testmicro.cpp
CONST	SEGMENT
??_C@_19EEPNDKNE@?$AA?$CF?$AAs?$AA?$AN?$AA?6?$AA?$AA@ DB '%', 00H, 's', 00H
	DB	0dH, 00H, 0aH, 00H, 00H, 00H			; `string'
CONST	ENDS
;	COMDAT ??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@
CONST	SEGMENT
??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@ DB 'M', 00H, 's', 00H, 'g', 00H
	DB	'1', 00H, 00H, 00H				; `string'
CONST	ENDS
;	COMDAT rtc$TMZ
rtc$TMZ	SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ	ENDS
;	COMDAT rtc$IMZ
rtc$IMZ	SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ	ENDS
;	COMDAT _wmain
_TEXT	SEGMENT
_szMsg1$ = -528						; size = 520
__$ArrayPad$ = -4					; size = 4
_argc$ = 8						; size = 4
_argv$ = 12						; size = 4
_wmain	PROC						; COMDAT

; 13   : {

  00000	55		 push	 ebp
  00001	8b ec		 mov	 ebp, esp
  00003	81 ec d4 02 00
	00		 sub	 esp, 724		; 000002d4H
  00009	53		 push	 ebx
  0000a	56		 push	 esi
  0000b	57		 push	 edi
  0000c	8d bd 2c fd ff
	ff		 lea	 edi, DWORD PTR [ebp-724]
  00012	b9 b5 00 00 00	 mov	 ecx, 181		; 000000b5H
  00017	b8 cc cc cc cc	 mov	 eax, -858993460		; ccccccccH
  0001c	f3 ab		 rep stosd
  0001e	a1 00 00 00 00	 mov	 eax, DWORD PTR ___security_cookie
  00023	33 c5		 xor	 eax, ebp
  00025	89 45 fc	 mov	 DWORD PTR __$ArrayPad$[ebp], eax

; 14   :     wchar_t szMsg1[_MAX_PATH];
; 15   : 
; 16   :     // _tcscpy(szMsg, L"Msg");
; 17   :     MY_PRINT(Msg1)

  00028	8b f4		 mov	 esi, esp
  0002a	68 00 00 00 00	 push	 OFFSET ??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@
  0002f	8d 85 f0 fd ff
	ff		 lea	 eax, DWORD PTR _szMsg1$[ebp]
  00035	50		 push	 eax
  00036	ff 15 00 00 00
	00		 call	 DWORD PTR __imp__wcscpy
  0003c	83 c4 08	 add	 esp, 8
  0003f	3b f4		 cmp	 esi, esp
  00041	e8 00 00 00 00	 call	 __RTC_CheckEsp

; 18   : 
; 19   :     _tprintf(L"%s\r\n", szMsg1);

  00046	8b f4		 mov	 esi, esp
  00048	8d 85 f0 fd ff
	ff		 lea	 eax, DWORD PTR _szMsg1$[ebp]
  0004e	50		 push	 eax
  0004f	68 00 00 00 00	 push	 OFFSET ??_C@_19EEPNDKNE@?$AA?$CF?$AAs?$AA?$AN?$AA?6?$AA?$AA@
  00054	ff 15 00 00 00
	00		 call	 DWORD PTR __imp__wprintf
  0005a	83 c4 08	 add	 esp, 8
  0005d	3b f4		 cmp	 esi, esp
  0005f	e8 00 00 00 00	 call	 __RTC_CheckEsp

; 20   : 
; 21   :     getwchar();

  00064	8b f4		 mov	 esi, esp
  00066	ff 15 00 00 00
	00		 call	 DWORD PTR __imp__getwchar
  0006c	3b f4		 cmp	 esi, esp
  0006e	e8 00 00 00 00	 call	 __RTC_CheckEsp

; 22   : 	return 0;

  00073	33 c0		 xor	 eax, eax

; 23   : }

  00075	52		 push	 edx
  00076	8b cd		 mov	 ecx, ebp
  00078	50		 push	 eax
  00079	8d 15 00 00 00
	00		 lea	 edx, DWORD PTR $LN5@wmain
  0007f	e8 00 00 00 00	 call	 @_RTC_CheckStackVars@8
  00084	58		 pop	 eax
  00085	5a		 pop	 edx
  00086	5f		 pop	 edi
  00087	5e		 pop	 esi
  00088	5b		 pop	 ebx
  00089	8b 4d fc	 mov	 ecx, DWORD PTR __$ArrayPad$[ebp]
  0008c	33 cd		 xor	 ecx, ebp
  0008e	e8 00 00 00 00	 call	 @__security_check_cookie@4
  00093	81 c4 d4 02 00
	00		 add	 esp, 724		; 000002d4H
  00099	3b ec		 cmp	 ebp, esp
  0009b	e8 00 00 00 00	 call	 __RTC_CheckEsp
  000a0	8b e5		 mov	 esp, ebp
  000a2	5d		 pop	 ebp
  000a3	c3		 ret	 0
$LN5@wmain:
  000a4	01 00 00 00	 DD	 1
  000a8	00 00 00 00	 DD	 $LN4@wmain
$LN4@wmain:
  000ac	f0 fd ff ff	 DD	 -528			; fffffdf0H
  000b0	08 02 00 00	 DD	 520			; 00000208H
  000b4	00 00 00 00	 DD	 $LN3@wmain
$LN3@wmain:
  000b8	73		 DB	 115			; 00000073H
  000b9	7a		 DB	 122			; 0000007aH
  000ba	4d		 DB	 77			; 0000004dH
  000bb	73		 DB	 115			; 00000073H
  000bc	67		 DB	 103			; 00000067H
  000bd	31		 DB	 49			; 00000031H
  000be	00		 DB	 0
_wmain	ENDP
_TEXT	ENDS
END


可以看到,  宏操作的串确实为一个const wchar_t *

;	COMDAT ??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@
CONST	SEGMENT
??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@ DB 'M', 00H, 's', 00H, 'g', 00H
	DB	'1', 00H, 00H, 00H				; `string'


宏操作该串的语句也为_tcscpy

; 17   :     MY_PRINT(Msg1)

  00028	8b f4		 mov	 esi, esp
  0002a	68 00 00 00 00	 push	 OFFSET ??_C@_19IIICNMM@?$AAM?$AAs?$AAg?$AA1?$AA?$AA@
  0002f	8d 85 f0 fd ff
	ff		 lea	 eax, DWORD PTR _szMsg1$[ebp]
  00035	50		 push	 eax
  00036	ff 15 00 00 00
	00		 call	 DWORD PTR __imp__wcscpy
  0003c	83 c4 08	 add	 esp, 8
  0003f	3b f4		 cmp	 esi, esp
  00041	e8 00 00 00 00	 call	 __RTC_CheckEsp


用类似的宏替换完成后, 工程会清爽好多.

 

最终版 宏定义的文件:

/// @file       ReLoadNtOsDefine.h
/// @note       重载内核API的宏定义, 使程序的书写简洁些

#ifndef __RE_LOAD_NT_OS_DEFINE_H__
#define __RE_LOAD_NT_OS_DEFINE_H__

/// ReLoadNtosCALL Micro Define

/// 宏的例子
/// _tcscpy(szMsg, L"Msg");
/// #define MY_PRINT(x) _tcscpy(sz##x, L#x);

#define  RE_LOAD_NTOS_CALL_API_NAME(x) ReLoadNtosCALL((PVOID)(&R##x),L#x,g_ulSystemKernelModuleBase,(ULONG)g_pImageModuleBase);

#define  RE_LOAD_NTOS_CALL_ExAllocatePool           RE_LOAD_NTOS_CALL_API_NAME(ExAllocatePool)
#define  RE_LOAD_NTOS_CALL_ExFreePool               RE_LOAD_NTOS_CALL_API_NAME(ExFreePool)
#define  RE_LOAD_NTOS_CALL_memcpy                   RE_LOAD_NTOS_CALL_API_NAME(memcpy)

#endif  // #ifndef __RE_LOAD_NT_OS_DEFINE_H__


 

 

 


 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐