⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mylock.asm

📁 关于pe文件的汇编语言
💻 ASM
📖 第 1 页 / 共 3 页
字号:

        call    encrypt_objects                 ; encrypt each section

        add     esi, 28h                        ; next section in table

        loop    Next_Section


        

;Find_Import_Section:
;
;       cmp	[esi],'adi.'			;查找Import块
;	jnz	Next_Section
;	or      [esi.SFlags], 80000000h		;改块属性为可写
;	jmp	Find_OK				;跳出查找
;Next_Section:
;        add     esi, 28h                        ;下个块
;
;        loop    Find_Import_Section
; ----- 添加新块 ----------------------------------
Find_OK:
        mov     esi, offset Section_Table            ;块表开始处
        movzx   eax, [PE_Header.NumberOfSections]    ;块表个数
        mov     ecx, 28h                        ;块表大小
        mul     ecx                             ;块表个数*块表大小
        add     esi, eax                        ;指向块表末
        inc     [PE_Header.NumberOfSections]         ;增加一个块
        mov     edi, offset new_section		;指向新的块表
        xchg    edi, esi

; ----- 按块对齐要求对齐新块/获得新块的RVA地址 -----------------------------------------------

        mov     eax, [edi-28h+8]                 
        add     eax, [edi-28h+0Ch]		;VirtualAddress加上VirtualSize=最后一块末的RVA(未对齐)
        mov     ecx, [PE_Header.SectionAlignment]	;块对齐大小
        cdq
        div     ecx
        test    edx, edx			
        jz      section_aligned			;对齐否(有无小数部分)
        inc     eax				;小数为近为一

section_aligned:

        mul     ecx				;对齐为FileAlignment(文件块对齐大小)的整被数
        mov     virt_addr, eax			;既是外壳程序的RVA地址
        mov     Checker_RVA, eax

; ----- 按文件对齐要求对齐 -------------------------------------

        mov     eax, Checker_Len		;外壳程序长度
        mov     ecx, [PE_Header.FileAlignment]	;文件块对齐大小
        div     ecx				;相除
        test    edx, edx
        jz      file_aligned			;对齐否?(有无小数部分)
        inc     eax				;小数为近为一

file_aligned:

        mul     ecx				;对齐为FileAlignment(文件块对齐大小)的整被数
        mov     [raw_size], eax			;保存

; ----- 对齐以获得VirtualSize --------------------------------------

        mov     eax, Checker_Len		;外壳程序长度
        mov     ecx, [PE_Header.SectionAlignment]	;块对齐大小
        div     ecx				;相除
        test    edx, edx			
        jz      sect_aligned			;对齐否?(有无小数部分)
        inc     eax				;小数为近为一

sect_aligned:

        mul     ecx				;对齐为SectionAlignment(块对齐大小)的整被数
        mov     virt_size, eax			;保存

; ----- 获得指向最末的文件指针 -------------------------------------------------

        mov     eax, [edi-28h+14h]		;最后一个块的物理偏移(PointerToRawData)
        add     eax, [edi-28h+10h]		;最后一个块的物理大小(SizeOfRawData)
        mov     raw_offset, eax			;相加后为指向最后一块末

; ----- 获得Import表的RVA地址和大小 ----------------------------------

        mov     eax, My_Import-Checker_Start	;外壳程序Import表相对外壳程序的偏移
        add     eax, Checker_RVA                           ;加上外壳程序基址RVA地址=外壳程序Import表RVA地址
        mov     [PE_Header.DataDirectory.(8).VirtualAddress], eax    ; data dir中的Import(输入块)的RVA地址
        mov     [PE_Header.DataDirectory.(8).Size], Import_Len           ; Import 的大小

        add     dword ptr My_Import, eax                ;都加上Import表RVA地址
        add     dword ptr k32_dll, eax                  ;
        add     dword ptr k32_first, eax                ;
        add     dword ptr func_k32, eax                 ;
        add     dword ptr [func_k32+4], eax             ;
        add     dword ptr [func_k32+8], eax             ;
        add     dword ptr [func_k32+0Ch], eax           ;

	add     dword ptr [func_k32+10h], eax           ;
	add     dword ptr [func_k32+14h], eax           ;

        add     dword ptr getproc, eax                  ;
        add     dword ptr getmod, eax                   ;
        add     dword ptr loadlib, eax                  ;

        add     dword ptr CreateF, eax                  ;
        add     dword ptr DeviceIo, eax                 ;

        add     dword ptr u32_original, eax             ;
        add     dword ptr u32_dll, eax                  ;
        add     dword ptr u32_first, eax                ;
        add     dword ptr func_u32, eax                 ;
        add     dword ptr msgbox, eax                   ;
        add     dword ptr Error_Cap_addr, eax                 ;
        add     dword ptr Error_Msg_addr, eax                 ;

; ----- 调整并对齐总长 ----------------------------------------

        mov     eax, virt_size				;外壳程序对齐后的大小
        add     eax, [PE_Header.SizeOfImage]			;加上原来的文件各部分总长
        mov     ecx, [PE_Header.SectionAlignment]		;块对齐大小
        div     ecx
        test    edx, edx				;是否对齐(有无小数部分)
        jz      image_aligned
        inc     eax					;小数为近为一

image_aligned:

        mul     ecx					;对齐为SectionAlignment(块对齐大小)的整被数
        mov     [PE_Header.SizeOfImage], eax			;写回去

; ----- 添加新块表 ----------------------------------------

        mov     ecx, 28h				;添上把新的块表项
        rep     movsb

; ----- 保存老的程序入口RVA地址 ---------------------------------------------

        mov     eax, dword ptr virt_addr		;外壳程序RVA地址
        mov     ebx, dword ptr [PE_Header.AddressOfEntryPoint]	;原来的程序入口
        mov     [PE_Header.AddressOfEntryPoint], eax			;保存新的程序入口
        mov     Old_Entry_RVA, ebx				;保存老的

; ----- 把新的PE文件头写入 -------------------------------------------------------

        push    FILE_BEGIN					;由文件开始处
        push    0
        push    PE_Header_Addr					;PE文件头的文件指针
        push    File_Handle					;文件句柄
        call    SetFilePointer					;设置文件读写指针

        push    0
        push    offset bytes_read
        push    Header_Len					;文件头长度
        push    offset PE_Header File_Handle				;内存中的文件头偏移 和 文件句柄
        call    WriteFile					;写到文件中

; ----- 写入外壳程序------------------------------------------------------

        push    FILE_BEGIN					;由文件开始处
        push    0
        push    raw_offset					;指向最后一块末
        push    File_Handle					;文件句柄
        call    SetFilePointer					;设置文件读写指针

        push    0
        push    offset bytes_read
        push    raw_size					;对齐了的外壳程序大小
        push    offset Checker_Start				;指向外壳程序开始处
        push    File_Handle					;文件句柄
        call    WriteFile					;写到文件中

	jmp     OK					;到关闭文件

; ----- 显示错误 --------------------------------------------------

no_space:					;没有足够未用空间装入新块表

       	push	0
	push	offset	Error_Msg
	push	offset	Error_nospace
	push	0
        call    MessageBoxA                     ; 调用User32!MessageBoxA生成对话框

        jmp     Close_File

not_valid_pe:					;不是有效的PE文件

	push	0
	push	offset	Error_Msg
	push	offset	Error_nope
	push	0
        call    MessageBoxA                     ; 调用User32!MessageBoxA生成对话框
        jmp     Close_File

Format_err:
	push	0
	push	offset 	Error_Msg
	push	offset 	Error_Format
	push	0
	call    MessageBoxA                     ; 调用User32!MessageBoxA生成对话框
	jmp     Close_File

Write_err:
	push	0
	push	offset 	Error_Msg
	push	offset 	Error_Write
	push	0
	call    MessageBoxA                     ; 调用User32!MessageBoxA生成对话框
	jmp     Close_File

file_not_found:					; 文件没找到

	push	0
	push	offset	Error_Msg
	push	offset	Error_nofile
	push	0
        call    MessageBoxA                     ; 调用User32!MessageBoxA生成对话框
        jmp     quit

; ----- 搞定了,关掉文件 -------------------------------------------------

OK:
	push	0
	push	offset	OK_Cap
	push	offset	OK_Msg
	push	0
        call    MessageBoxA                     ; 调用User32!MessageBoxA生成对话框
Close_File:

        push    File_Handle                     ;文件句柄
        call    CloseHandle			;关闭文件

quit:

        push    0				
        call    ExitProcess			;退出程序

;------------------------------------------------------------------------------
  show_some_info proc
;------------------------------------------------------------------------------

        mov     eax, [PE_Header.SizeOfCode]		;获得SizeOfCode
        push    eax eax
        movzx   eax, [PE_Header.NumberOfSections]	;获得NumberOfSections
        push    eax offset num_secs
	mov	P_Text,offset Text_Buff			;字符输出缓冲区地址
        call    My_Printf				;调用printf

        mov     eax, [PE_Header.SizeOfInitializedData]
        push    eax eax
        mov     eax, [PE_Header.ImageBase]
        push    eax offset img_base
        call    My_Printf

        mov     eax, [PE_Header.SizeOfUninitializedData]
        push    eax eax
        mov     eax, [PE_Header.AddressOfEntryPoint]
        push    eax offset ep_rva
        call    My_Printf

        mov     eax, [PE_Header.SectionAlignment]
        push    eax eax
        mov     eax, [PE_Header.SizeOfImage]
        push    eax offset size_img
        call    My_Printf

        mov     eax, [PE_Header.FileAlignment]
        push    eax eax
        mov     eax, [PE_Header.SizeOfHeaders]
        push    eax offset size_head
        call    My_Printf

        movzx   eax, [PE_Header.MinorLinkerVersion]
        push    eax
        movzx   eax, [PE_Header.MajorLinkerVersion]
        push    eax
        mov     eax, [PE_Header.BaseOfCode]
        push    eax offset base_code
        call    My_Printf

        movzx   eax, [PE_Header.DllCharacteristics]
        push    eax eax
        mov     eax, [PE_Header.BaseOfData]
        push    eax  offset base_data
        call    My_Printf

	push    0
	push	offset Welcome				;对话框标题
	push    offset Text_Buff			;指向要输出的字符串
	push	0
        call    MessageBoxA				;生成对话框,显示文件信息

        ret
endp
extrn   _wsprintfA:proc
My_Printf     proc    
        pop	ebx				;保存返回地址
	push    P_Text				;输出缓冲区
        call    _wsprintfA			;调用Printf
        add     esp, 4*5			;恢复栈指针
	add	eax,P_Text			;修改输出缓冲区地址
	mov	P_Text,	eax
	push	ebx				;返回
	ret
endp

extrn   VirtualAlloc:proc
extrn   VirtualFree:proc
encrypt_objects proc

        pusha
	cmp	[esi], 'rsr.'			; 跳过 .rsrc块
	jz      no_encrypt
	cmp     [esi], 'adr.'                   ; 跳过 .rdata块
        jz      no_encrypt
        cmp     [esi], 'ade.'                   ; 跳过 .edata块
        jz      no_encrypt
        cmp     [esi], 'ler.'                   ; 跳过 .reloc块
        jz      no_encrypt
        cmp     [esi], 'slt.'                   ; 跳过 .tls块
        jz      no_encrypt
        cmp     dword ptr [esi.SizeOfRawData], 0	;块大小是否是零
        jz      no_encrypt

        push    PAGE_READWRITE
        push    MEM_COMMIT
        push    [esi.SizeOfRawData]
        push    0
        call    VirtualAlloc				;分配一块内存

        mov     mem_offset, eax				;返回的是内存首址

; ----- 读入该块数据 -----------------------------------------------

        push    0
        push    0
        push    [esi.PointerToRawData]			; 该块的物理位置
        push    File_Handle				; 文件句柄
	call    SetFilePointer				; 设置文件指针

        push    0
        push    offset bytes_read
        push    [esi.SizeOfRawData]			; 该块大小
        push    mem_offset				; 在已分配的内存处
        push    File_Handle				; 文件句柄
        call    ReadFile				; 读入

; ----- 保存该块的RVA地址和大小 -------------------------------------------

        mov     edi, [curr_disp]
        mov     eax, [esi+SVirtualAddress]		; 获得该块的RVA地址
        mov     [ENsection_RVA+edi], eax                   ; 保存该块的RVA地址

        mov     eax, [esi.SizeOfRawData]		; 获得该块的大小
        mov     [ENsection_Len+edi], eax                  ; 保存该块的大小

        mov     edi, mem_offset                         ; 已分配的内存首址
        mov     ecx, [esi.SizeOfRawData]                ; 块大小(要加密的字节数)
        mov     al, key                                 ; 加密密匙

encrypt:

        sub     byte ptr [edi], al                      ; 加密
        inc     al
        inc     edi                                     ; 继续
        loop    encrypt

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -