📄 mylock.asm
字号:
; ----- write encrypted section -----------------------------------------------
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 WriteFile ; 写入
; ----- deallocate memory -----------------------------------------------------
release_mem:
push MEM_DECOMMIT ; fdwFreeType
push [esi.SizeOfRawData] ; cbSize
push mem_offset ; lpvAddress
call VirtualFree
;----- update flags/number of objects -----------------------------------------
add [curr_disp], 8 ; update displacement
inc byte ptr ENsection_Number ; update counter
or [esi.SFlags], 80000000h ; enable write bit
no_encrypt:
popa
ret
encrypt_objects endp
;**********************************to ring 0 ;进入ring 0(0级)
Into_Ring_0 proc
pushad
push eax ;
sidt [esp-02h] ; 获得中断描述符表的基址到ebx
pop ebx ;
add ebx, 5*08h+04h ;计算要用中断的基址到ebx
cli ;在改表项前关中断
mov ebp, [ebx]
mov bp, [ebx-04h] ;取得中断基址到ebp
mov esi,offset MyExceptionHook
push esi ;esi为中断例程地址
mov [ebx-04h], si
shr esi, 16
mov [ebx+02h], si ;修改中断基址使指向中断例程
pop esi
; *************************************
; * Generate Exception to Get Ring0 *
; *************************************
int 5 ;以中断的方式进入0级
jmp NNN
MyExceptionHook:
mov byte ptr ss:[522h+4],012h ;每磁道18个扇区
ExitRing0Init:
mov [ebx-04h], bp ;
shr ebp, 16 ;
mov [ebx+02h], bp ; ;恢复原来的中断基址
iretd ;中断返回
NNN:
popad
ret
Into_Ring_0 endp
.DATA
;--------------------外壳程序-----------------------------------------------
Checker_Start:
db '[SPEC]'
call Go_In
Go_In:
pop ebp ;获得实际偏移
mov eax, ebp
sub ebp, offset Go_In ;减去原来的偏移=原来地址和现在地址之差
sub eax, [Checker_RVA+ebp] ;当前地址减去该块的RVA地址
sub eax, offset Go_In-Checker_Start ;再减去Go_In到Checker_Start=当前基址
mov [Image_Base+ebp], eax ;保存新的基址
mov edi, ebp ;地址差
;------------验证------------------------------------------
lea esi,SICE_MOD+ebp
push NULL
push 80h
push 3
push 0
push 3
push 0c0000000h
push esi
call [CreateF+ebp]
cmp eax,-1
jnz exit_loader
; jmp De
no_softice:
lea esi,File+ebp
push NULL
push FILE_FLAG_DELETE_ON_CLOSE
push 0
push 0
push 3
push 0
push esi
call [CreateF+ebp]
;mov hDevice+ebp,eax
jmp nof
mov reg_EAX+ebp,0511h
mov reg_EDX+ebp,0100h
mov reg_ECX+ebp,1700h
lea ebx,Format_ID+ebp
mov reg_EBX+ebp,ebx
push 0
lea ebx,CB+ebp
push ebx
push 7*4
lea ebx,REGS+ebp
push ebx
push 7*4
push ebx
push 4
push eax
call [DeviceIo+ebp]
nof:
mov reg_EAX+ebp,0201h
mov reg_EDX+ebp,0000h
mov reg_ECX+ebp,0001h
lea ebx,Disk_Buffer+ebp
mov reg_EBX+ebp,ebx
push 0
lea ebx,CB+ebp
push ebx
push 7*4
lea ebx,REGS+ebp
push ebx
push 7*4
push ebx
push 4
push eax
call [DeviceIo+ebp]
and reg_Flags+ebp,0001h
jnz exit_loader
mov ecx,512
xor eax,eax
mov edx,ebp
nextadd:
add eax,dword ptr Disk_Buffer+edx
add edx,4
loop nextadd
cmp eax,disk_key+ebp
jnz exit_loader
;*******************************************************8;
De:
movzx esi, [ENsection_Number+ebp] ; 获得被加密的块数
; mov edi, ebp ; 地址差
Next_Sec:
mov ebx, [Image_Base+ebp] ; 获得基址
mov eax, [ENsection_RVA+edi] ; 被加密块的RVA地址
add ebx, eax ; 内存中的实际地址
mov ecx, [ENsection_Len+edi] ; 该块的大小
mov al, [key+ebp] ; 解密密匙
decrypt:
add byte ptr [ebx], al ; 解密还原
inc al
inc ebx ; 继续
loop decrypt
add edi, 8 ; 下一个块
dec esi ; 块计数减一
jnz Next_Sec ; 是否解完
; ----- 对原来的Import表(输入表)进行人工填写(重定位) ----------------------------------------------------
no_de:
mov edx, [Image_Base+ebp] ; 基址
mov esi, [Import_Address+ebp] ; Import表的RVA地址
add esi, edx ; 相加后就是Import表的实际地址
next_dll:
mov eax, [esi+0Ch] ; Dll的文件名RVA地址
or eax, eax
jz dll_end ; 是否存在(是NULL就不存在),转到dll_end
add eax, edx ; 加上基址
mov ebx, eax ; 保存到ebx
push eax ;
call [getmod+ebp] ; 调用Kernel32!GetModuleHandleA以获得模块句柄
or eax, eax
jnz dll_loaded ; 是否已经装入了,如果装入了就转dll_loaded
push ebx ;
call [loadlib+ebp] ; 调用Kernel!LoadLibrary装入模块
or eax, eax ; 成功了就返回该模块句柄
jnz dll_loaded
exit_loader:
mov edx, [Image_Base+ebp] ; 获得基址
add [Error_Cap_addr+ebp], edx ; 对话框标题的地址加上基址
add [Error_Msg_addr+ebp], edx ; 对话框内容加上基址
push 0 ; Null
push [Error_Cap_addr+ebp] ; 对话框标题的地址
push [Error_Msg_addr+ebp] ; 对话框内容加上基址
push 0 ; MB_OK
call [msgbox+ebp] ; 调用User32!MessageBoxA
push 0
call [exitproc+ebp] ; 调用Kernel32!ExitProcess
dll_loaded:
mov [Dll_Handle+ebp], eax ; 保存该模块句柄
mov [Func_Point+ebp], 0 ; Func_Point是表项指针,指示是第几个功能调用
next_function:
mov edx, [ebp+Image_Base] ; 基址
mov eax, [esi] ; Import表第一项Characteristics(是RVA地址)
or eax, eax ; 是否存在
jnz hint_ok
mov eax, [esi+10h] ; 指向输入地址表数组(PIMAGE_THUNK_DATA FirstThunk)的指针
hint_ok:
add eax, edx ; 加上基址
add eax, [Func_Point+ebp] ; Func_Point是表项指针,指示是第几个功能调用
mov ebx, [eax] ; 功能名的地址
mov edi, [esi+10h] ; 指向输入地址表数组(PIMAGE_THUNK_DATA FirstThunk)的指针
add edi, edx ; 加上基址
add edi, [Func_Point+ebp] ; 加上表项指针
test ebx, ebx ; 功能是否存在
jz function_end ; 不存在就处理下一个Dll
test ebx, 80000000h ; 是否是序列号
jnz func_ordinal
add ebx, edx ; 加上基址=提示名表地址(Hint Name Table)
add ebx, 2 ; Hint为两个字节
func_ordinal:
and ebx, 0FFFFFFFh ; 屏蔽高8位
push ebx ; 功能名的字符偏移
push dword ptr [ebp+Dll_Handle] ; 模块的句柄
call [getproc+ebp] ; 调用Kernel32!GetpProcAddress以获得功能调用地址
or eax, eax ; 成功否
jz exit_loader
mov [edi], eax ; 保存到输入地址表(Import Address Table)
add [Func_Point+ebp], 4 ; 下一个功能
jmp next_function ; 处理下一个功能
function_end:
add esi, 14h ; 下一个表项
mov edx, [Image_Base+ebp] ; 加上基址
jmp next_dll ; 处理下一个模块
dll_end:
mov eax, [Old_Entry_RVA+ebp] ; 原程序入口RVA地址
add eax, [Image_Base+ebp] ; 加上基址
jmp eax ; 跳到原程序执行
;------------------------构造外壳程序的Import表-----------------------------------
align 4 ;以4字节对齐
My_Import dd func_k32-My_Import ; Kernel32.dll的Characteristics指向提示名表(HintNameTable)
dd 0,0 ; 时间标记和正向链接索引(TimeDataStamp and ForwarderChain)
k32_dll dd k32-My_Import ; Kernel32.dll的文件名的RVA地址
k32_first dd getproc-My_Import ; 指向Kernel32.dll输入地址表(Import Address Table)
; 第一个调用为GetProcAddress
u32_original dd func_u32-My_Import ; User32.dll的Characteristics指向提示名表(HintNameTable)
dd 0,0
u32_dll dd u32-My_Import ; User32.dll的文件名的RVA地址
u32_first dd msgbox-My_Import
dd 5 dup (0) ; Import表的结束符
k32 db 'KERNEL32.DLL',0 ; Kernel32.dll的文件名
func_k32 dd function1-My_Import ; 提示名表(HintNameTable),都是RVA地址
dd function2-My_Import
dd function3-My_Import
dd function4-My_Import
dd function6-My_Import
dd function7-My_Import,0
u32 db 'USER32.DLL',0 ; User32.dll的文件名
func_u32 dd function5-My_Import,0
getproc dd 0 ; 输入地址表(Import Address Table)
getmod dd 0 ; 由PE装入器填入
loadlib dd 0
exitproc dd 0
CreateF dd 0
DeviceIo dd 0
msgbox dd 0
dd 0 ; 结束符
function1 db 0,0,'GetProcAddress',0 ; 功能调用的字符表
function2 db 0,0,'GetModuleHandleA',0
function3 db 0,0,'LoadLibraryA',0
function4 db 0,0,'ExitProcess',0
function6 db 0,0,'CreateFileA',0
function7 db 0,0,'DeviceIoControl',0
function5 db 0,0,'MessageBoxA',0
align 4
Import_End:
Error_Cap_addr dd Error_Cap-My_Import ; 对话框标题的地址
Error_Msg_addr dd Error_Msg_1-My_Import ; 对话框内容
Error_Cap db '出错',0 ; 对话框标题
Error_Msg_1 db '装入失败',0 ; 对话框内容
Dll_Handle dd 0 ; 模块的句柄
Func_Point dd 0 ; 表项指针,指示是第几个功能调用
Import_Address dd 0 ; 原输入表的RVA地址
Checker_RVA dd 0 ; 外壳程序的RVA地址
Image_Base dd 0 ; 基址
Old_Entry_RVA dd 0 ; 原程序的入口RVA地址
ENsection_Number db 0 ; 被加密的块数
key db 0 ; 块的解密匙
ENsection_RVA dd 0 ; 被加密的块的RVA地址和块大小(预设5个块的位置)
ENsection_Len dd 0
dd 20h dup (0)
disk_key dd 04517ebB0h
File db "\\.\vwin32",0
SICE_MOD db "\\.\SICE",0
CB dd 0h
REGS = $
reg_EBX dd 0
reg_EDX dd 0
reg_ECX dd 0
reg_EAX dd 0
reg_EDI dd 0
reg_ESI dd 0
reg_Flags dd 0
Disk_Buffer db 512 dup(0)
Checker_End:
;------------------------------------------------------------------------------
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -