📄 mylock.asm
字号:
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 + -