1。栈溢出介绍
缓冲区溢出主要是程序在设计时边界的限制不严格,导致缓冲区数据越出边界,覆盖掉旁边的数据
,如果覆盖后的数据是经过精心设计的,那么就会存在严重的漏洞,可以通过此漏洞执行任意的程
序代理。
主要的实现过程:
数据溢出后,此时通过计算程序返回地址,把一个JMP ESP的跳转指令地址(通用地址为0x7ffa4512)覆盖到返回地址上(也就是返回地址CS:IP上),那么此时CS:IP就跳到JMP ESP的指令上执行这条指令,而ESP的值正好指向返回地址的下一条指令,此时在返回地址后面覆盖上设计好的shellcode就可以放程序运行次程序,完成攻击.示意图如下:

NNNNNNNNN....RET(0X7FFA4512)  SHELLCODE
               |                 |
               jmp esp---------- |
补充:
有时SHELLCODE覆盖的数据区是不能读的,于是就会造成程序错误,与是还有一种办法就是把
shellcode调到前面,在返回地址后面不用shellcode覆盖,而是用一条JMP跳转指令跳转到前面的可读的数据区+shellcode,这样也可以执行SHELLCODE。

另外一种常用的溢出方法JMP EBX
通过对返回地址覆盖上一个不可读写的地址,造成程序错误,程序转入异常处理机制,这时找到处
理入口(0x7ffa1571 jmp ebx通用地址),计算返回地址与入口地址距离,然后他们之间覆盖上NOP直到入口前4个字节,前4个字节输入JMP 04,后面接着输入JMP EBX  接着shellcode(提示:JMP EBX就是跳转到自身地址的前4个字节)

NNNNNNNNNNN....  RET(造成异常地址)  NNNNNNNNNN  JMP 04   入口(JMP EBX)shellcode
                     |                                     |
                     |-------------------------------------|
                           (转入异常处理程序入口)

2.shellcode的编写
环境:VC++6。0
用汇编语言实现程序要的功能,然后编译没错后,F10开始调试,进入反汇编,复制机器码。OK
函数的调用是先把参数从右到左(视情况而顶)压栈,然后CALL 函数地址(call函数执行PUSH IP 然后JMP)。

| -------------
|    EBP    |     这部开始都是在函数内部执行,这条是保护原来的堆栈基址 
| -------------
|     IP   |    这部之后程序指令调到API函数的入口
| -------------
|   第N个  |
|    参数    |      程序调用API时堆栈的结构
| -------------
|  第一个 |
|   参数    |
 -------------

3.远程shellcode的编写
远程的SHELLCODE需要在攻击端打开一个SHELL,并实现shell命令在双方的传递与显示(IPC进程间通信),其中存在管道方式,事件,文件映射,邮槽。(目前了解下管道)
执行过成:
客户端建立连接之后,服务端监听到有连接进来,与是接受连接,建立管道(分为双管道,单管道
,0管道),然后开启一个SHELL,他们之间用管道传递命令。

                                              管道1(把命令传给CMD)      
攻击端------------------------>被攻击端----------------------------------------------cmd.exe
                                       ----------------------------------------------cmd.exe
                                              管道2(把命令的结果回显)

      以上为双管道

                                     没执行一个命令,都把命令做为参数,从新开启一个新CMD  
攻击端------------------------>被攻击端----------------------------------------------cmd.exe  
                                               管道1(传回显)

      以上为单管道

0管道不用管道,直接通过SOCKET传命令,命令到达都立即执行

另一冲连接,反向的shellcode连接,由被攻击端主动来连接攻击端,可使用双管道,单管道等。  

4.堆溢出(heap)
堆是一种程序在运行期间动态生成的一种内存结构,与堆栈的增长方向相反,是往高地址长。
堆结构:
   8字节                8个字节各占4个(前指针4字节|后指针4字节)  
  -------------------------------------------------------
 |堆管理 | 堆操作空间| 下一个空闲堆管理结构| 两个双链表 |
    ------- -----------------------------------
    堆结构

我们通过对数据以及链表等地方做覆盖,在链表上分为2个4字节的链表,当数据覆盖到双链表前4
个字节时就会出错,以及给下一个堆分配空间时也会出现错误而执行mov [ecx],eax,mov [eax+4],ecx.这2条指令
    eax          ecx
--------------  ---------------
   what=    |   where=    |双链表的结构,会执行上面2条命令,所以如果调用了ecx里面的函
shellcode   |    函数      |数入口地址指针,就会执行这个函数,我们还是在用mov[ecx],eax
    地址     |   返回地址   |把函数入口地址指针(在ECX中的值是指向函数入口地址指针)
--------------  --------------  改成了shellcode的入口地址,于是运行函数就等于在帮我们执行们                        shellcode.(需要注意第二句指令会改变shellcode+4位置的代  
                          码)在函数退出时调用也是好办法.
还有一种方法就是通过异常(SEH)调用
现在我们在定位shellcode的地址上没有很好的定位,现在我门来把他实现,把shellcode的地址用[esi+0x4c]来替代,由于[esi+0x4c]指向下一个堆管理结构,那么我们现在where里写上异常调用的地址指针,执行mov [ecx],eax后,把esi+0x4c的地址给异常函数第二句mov [eax+4],ecx 我们尽量使[eax+4]的内容不能写,产生错误,调用之前我们设计的异常(也就是shellcode地址)

5.shellcode的编码
如有些shellcode在编写完之后中间会出现一些不符合规定的字符,如在strcmp()函数中不允许有0x00,这回阻止程序的运行,因为程序以为0x00是字符串结尾,那么shellcode就需要编码来解决这个问题,让程序中不出现不符合规定的字符,这其中大体的思想是:
shellcode  +  一种编码方式(如xor,等) = enshellcode
而在如strcmp()等函数执行后,把shellcode反编码成原始shellcode,所以这也决定shellcode的编码方式必须是可逆的,shellcode编码结构:
enshellcode
......
shellcode

这样shellcode就可以被解码.
shellcode的基本编码方式:
XOR方法
shellcode xor Key  =  enshellcode
enshellcode xor Key = shellcode

微调法
如果只是一二个地方需要改动,就改变指令的方式调整那一小部分

拆分法
把一个数拆分成几个数,如
Z = a + b
Z = a * b

直接替换法
就在shellcode中直接对XOR后的结果中还存在不符合的数据进行一种方式的直接替换

内寸搜索法
对那些shellcode地址长度有限制的程序,直接在后面接上搜索shellcode的代码+shellcode.
通常搜索代码都很小,不长,所以都能很好的执行,另外在shellcode中添加用于搜索的标记,方便搜索代码用来执行搜索shellcode地址的任务

6.shellcode高级编程(动态定位函数地址以及从高级语言提出shellcode代码)
由于在shellcode执行中,在个系统种的通用性是最重要的,而通用性需要解决的问题就是调用系统DLL提供的函数时的动态内存地址,所以解决了这个问题后
shellcode + 通用的JMP ESP等跳转地址 = 通用的shellcode
定位函数的内存地址又分为几步
1。定位kernel32.DLL程序基地址
2。在DLL中保存了各种它包含的函数的内存地址,通过搜索这个表查找函数GetprocAddress函数的地址,通过这个函数就可以查出其他函数的地址

至于shellcode的提取可以用直接内存复制,调试时内存复制.通过高级语言直接提取

介绍蠕虫与突破防火墙的方法
蠕虫会把本机做成一个TFTP或FTP或各种传输服务,通过在本地打开一个端口监听,另外同时还在
对网络上计算机进行漏洞扫描,查找到有漏洞计算机后,对它进行攻击,执行从本机的下载工作,把本机上准备的病毒程序传到网络计算机

突破防火墙
使用反向连接,被攻击者主动连接攻击者,而如果攻击者在内网,那么数据包无法到达目的地,须

借助二机本身建立的攻击连接.
还可以通过对放火墙允许连接的端口做复用突破限制.

7.漏洞的分析,发现与攻击
漏洞的分析与发现通常都是通过2种方法实现的
1黑盒测试Fuzzer
这种方法不需要对程序的内部结构,逻辑结构,内部运做有了解,就想是把程序当成一个不能打开
密封的盒子来做测试,主要通过输入数据,在程序的借口对程序做测试,如对字符边界,数组大小,程序输入长度,逻辑错误等做检测,以此发现漏洞
2白盒测试
需要对程序的结构,内部的运行过程等都要有了解。反逆向来进行对结构的认识,查找漏洞。
通常程序都是结合2种方法一起测试的.
注:介绍了一种脚本语言python进行对软件接口,输入等的测试,python是一种在测试中很强大方便的测试工具,实时,对字符串的构造,把大部分的网络协议进行了封装,方便使用.
-----------------------------------------------------------------------

由于本人技术很菜 ,如有理解错误处,请大牛门指教. 



2008.07.01 by hokers