前几天在暗组的一个论坛上看到一个人写的ShellCode代码,感觉有点意,大家可以取之精华去之垃圾!!!于是把源代码粘上来,与大家学习学习~~
;=====================================================
; ShellCode For MASM32 Example By Anskya
; Email:Anskya@Gmail.com
; Web:
Www.Anskya.Net
; Thank: [29A Virus Group],EliCZ,Drocon....and your
;=====================================================
; 照z0mbie和Drocon等人的TASM代码自己用MASM32重组了一下
; 使用的是xCrc32b算法..具体说明可以参照偶在看雪论坛发布
; 的一篇文章.希望各位前辈批评指正..
; ShellCode提取非常容易.WinHex打开EXE,直接从
; $Shell_Begin$----$ShellCode_TheEnd$之间的数据全部复制
; 下来就OK了...另外说明:我喜欢ShellCode但是我不喜欢溢出
;=====================================================
.386
.model flat,stdcall
option casemap :none
;导入API函数声明
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include useful.inc
;导入完毕
;=============代码部份========================
.code
db '$Shell_Begin$'
;代码起始地址
start:
;int 3
pushad
call @@delta
@@delta: ; 代码起始部份
pop ebp
sub ebp,offset @@delta ; 代码自定位--熟悉吧
@@LoadApi: ; 搜索加载API函数
lea eax,[ebp+u32_api] ; 压入user32.dll的字符串以及函数HASH偏移
push eax ; 压栈
call search_dllapi ; 搜!!!!
@@MainProc: ; 不说了~
sub eax,eax
push eax
push eax
push eax
push eax
call [ebp+__MessageBoxA]
@@ExitProc: ; 结束部份
popad
ret
;------------------以下是代码需要的一些数据常量-----------
u32_api:
db 'user32',0
__MessageBoxA dd 0572D5D8Eh
dd 0
; 循环搜索一个DLL中的所有API函数----stdcall调用规则
; lea eax,[ebp+u32_api] ;数组的内存偏移
; push eax
; call search_dllapi
search_dllapi proc
pushad
mov esi,[esp+8*4+4] ;获取传入参数1
call get_k32base
push 04134D1ADh ;LoadLibraryA
push eax
call xGetProcAddress ;获取LoadLibraryA地址
push esi ;压入DLL字符串地址
call eax ;调用LoadLibraryA载入DLL
mov ebx,eax ;基址保存在ebx
sub eax,eax ;eax清0
lodsb ;读取函数HASH
test al,al ;判断读取失败
jnz $-3 ;
mov edi,esi
@@loop:
lodsd ;循环读取函数HASH
test eax,eax ;如果为0
jz @@end ;跳转到结束
push eax ;压入HASH
push ebx ;压入DLL基址
call xGetProcAddress ;搜索API
stosd ;写入原HASH保存地址
jmp @@loop ;循环
@@end:
popad
ret 4 ;一共压入1个参数恢复堆践4
search_dllapi endp
; xGetProcAddress(HMODULE hModule, DWORD ldHASH)--------Anskya..使用xCrc32算法
; stdcall调用模式--函数自动清除堆践
; push 0EC0E4E8Eh ---API HASH值
; push 0FF760000h ---DLL 基址
; call xGetProcAddress
; eax = API Addr--EAX返回API地址--没有返回0
xGetProcAddress proc
pushad ;保存寄存器环境
mov ebp, [esp + 8*4+4] ;从堆践中取出DLL基址
mov eax, [ebp + 3ch] ;eax = PE header offset
mov edx, [ebp + eax + 78h] ;导出表虚拟偏移:Export Table RVA
add edx, ebp ;edx = exports directory table */
mov ecx, [edx + 18h] ; ecx = number of name pointers */
mov ebx, [edx + 20h]
add ebx, ebp ; ebx = name pointers table */
LFnlp:
jecxz LNtfnd
dec ecx
mov esi, [ebx + ecx * 4]
add esi, ebp
xor edi, edi
;字符串Hash计算过程..xCrc32b算法---具体看以前我写的文章好了
;input: ESI=data
;output:EDI=hash
HashCalc: ;熟悉吧~熟悉不过了---
pushad
mov edx, esi
xor eax, eax
not eax
@@1:
xor al, [edx]
mov bl, 8
@@2:
shr eax, 1
jnc @@3
xor eax, 0EDB88320h ; crc32系列算法的标志
@@3:
dec bl
jnz @@2
cmp byte ptr [edx], 0
je @@4
inc edx
jmp @@1
@@4:
not eax
@@5:
mov [esp+pushad_edi],eax ;保存计算的hash
popad
LFnd:
cmp edi, [esp + param2] ; 比较当前字符串的Hash于查找的是否一样 */
jnz LFnlp
mov ebx, [edx + 24h] ; ebx = ordinals table RNA */
add ebx, ebp
mov cx, [ebx + 2*ecx] ; ecx = function ordinal */
mov ebx, [edx + 1ch] ; ebx = address table RVA */
add ebx, ebp
mov eax, [ebx + 4*ecx] ; eax = address of function RVA */
add eax, ebp ; EAX(函数地址) = eax函数相对RVA + ebp(DLL基址)
jmp short LDone
LNtfnd:
sub eax,eax ;如果没有找到函数地址将返回0
LDone:
mov [esp+pushad_eax],eax ;API地址保存eax中
popad ;恢复寄存器
ret 4 * 2 ;清除堆践..一共压入2个参数.清除 4 * 2
xGetProcAddress endp
;void* get_k32base()
;获取k32 Base ,k32基址保存在eax中
get_k32base proc ;获取k32 Base ,k32基址保存在eax中
pushad
assume fs: nothing
xor eax,eax
mov eax,fs:[eax+30h]
test eax,eax
js @@os_9x
@@os_nt:
mov eax,[eax+0ch]
mov esi,[eax+1ch]
lodsd
mov eax,[eax+8]
jmp @@finished
@@os_9x:
mov eax,[eax+34h]
lea eax,[eax+7ch]
mov eax,[eax+3ch]
@@finished:
mov [esp+7 * 4],eax ;7 * 4 刚好是popad后~~eax的位置
popad
ret
get_k32base endp
db '$ShellCode_TheEnd$'
shellcode_size equ $-start
mov eax,shellcode_size
push eax ;其实这里执行不到的...
call ExitProcess ;Win2k下没有导入表无法运行..这里随便填写了一个
end start
代码中的注释写的很详细,这里我就不罗里他索的了,直接研究代码吧!!!
[课程]Linux pwn 探索篇!