ShellCode编写历程

 

获取dll列表,并定位kernel32.dll:
 mov   eax,fs:[30h]
  test  eax,eax
  js  os_9x
os_nt:  
  mov  eax,[eax+0ch]
  mov  esi,[eax+1ch]
  lodsd  
  mov   eax,[eax+8]
  jmp  k_finished
os_9x:
  mov   eax,[eax+34h]
  mov  eax,[eax+7ch]
  mov  eax,[eax+3ch]
k_finished:
  sub  esp,200
  mov  edi,esp
  mov  [edi+8],eax  ;获取kernel32地址  
寻找方式如下:
 
               
获得kernel32基地址后,
                
                
                
                
在kernel32基址+0x3c处获取e_lfanewc地址,即可以得到PE头
先了解一下PE格式:
每个windows的PE格式如下:
                
                
                
                
DOS MZ header
DOS stub
PE header
Section table
Section 1
Section 2
Section ...
Section n
PE头其实就是如下结构:
IMAGE_NT_HEADERS STRUCT 
Signature dd ‘PE/0/0’
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS ENDS
其中,opt结构里含有
IMAGE_DATA_DIRECTORY,在这里可以找到导入表地址。
IMAGE_OPTIONAL_HEADER32 STRUCT
....
LoaderFlags dd ?
NumberOfRvaAndSizes dd ?
DataDirectory IMAGE_DATA_DIRECTORY 16 dup(<>)
IMAGE_OPTIONAL_HEADER32 ENDS
image_data_directory数组里的第13个元素既是导入表相关结构,而第一个元素为导出表相关结构。
 
                   
Member Info inside
0 Export symbols
1 Import symbols
2 Resources
3 Exception
4 Security
5 Base relocation
6 Debug
7 Copyright string
8 Unknown
9 Thread local storage (TLS)
10 Load configuration
11 Bound Import
12 Import Address Table
13 Delay Import
14 COM descriptor

 

data directory结构如下:

 

IMAGE_DATA_DIRECTORY STRUCT
VirtualAddress dd ?
isize dd ?
IMAGE_DATA_DIRECTORY ENDS

 

其中只包含地址和大小。

定位到Export表,其中

 

共有11 个成员,常用的列于下表。

 

Field Name Meaning
nName 模块的真实名称。本域是必须的,因为文件名可能会改变。这种情况下,PE装载器将使用这个内部名字。
nBase 基数,加上序数就是函数地址数组的索引值了。
NumberOfFunctions 模块引出的函数/符号总数。
NumberOfNames 通过名字引出的函数/符号数目。该值不是模块引出的函数/符号总数,这是由上面的NumberOfFunctions给出。本域可以为0,表示模块可能仅仅通过序数引出。如果模块根本不引出任何函数/符号,那么数据目录中引出表的RVA为0。
AddressOfFunctions 模块中有一个指向所有函数/符号的RVAs数组,本域就是指向该RVAs数组的RVA。简言之,模块中所有函数的RVAs都保存在一个数组里,本域就指向这个数组的首地址。
AddressOfNames 类似上个域,模块中有一个指向所有函数名的RVAs数组,本域就是指向该RVAs数组的RVA。
AddressOfNameOrdinals RVA,指向包含上述 AddressOfNames数组中相关函数之序数的16位数组。


 

FindApi: ;获取API函数地址子过程 push ebp push edi mov ebp,edi mov ebx,esp add ebx,8 xor edx,edx mov eax,[ebp+8] add eax,3ch ;指向PE头部偏移值e_lfanew mov eax,[eax] ;取得e_lfanew值 add eax,[ebp+8] ;指向PE header cmp dword ptr[eax],4550h ;判断是否为'PE' jne NotFound ;kernel32基址错误 mov [ebp+0ch],eax ;保存PE文件头 mov eax,[eax+78h] add eax,[ebp+8] mov [ebp+0ch],eax ;指向IMAGE_EXPORT_DIRECTORY mov eax,[eax+20h] add eax,[ebp+8] mov [ebp+4],eax ;保存函数名指针数组的指针值 mov ecx,[ebp+0ch] mov ecx,[ecx+14h] FindLoop: push ecx mov eax,[eax] add eax,[ebp+8] mov esi,ebx add esi,8 mov edi,eax mov ecx,[ebx+4] cld repe cmpsb jne FindNext add esp,4 mov eax,[ebp+0ch] mov eax,[eax+1ch] add eax,[ebp+8] shl edx,2 add eax,edx mov eax,[eax] add eax,[ebp+8] jmp Found FindNext: inc edx add dword ptr[ebp+4],4 mov eax,[ebp+4] pop ecx loop FindLoop NotFound: xor eax,eax Found: pop edi pop ebp ret  

 

你可能感兴趣的:(exception,struct,image,header,import,resources)