我想把字符串转变为shellcode显示出来,可是却有问题了
首先下面是我的hello.s文件来显示"Hello, World\n"
下面的代码是AT&T的语法,不是Intel的,所以用的是as编译器,
而不是 nasm
这个文件可以正常的把"Hello, World\n" 打印出来(问题不在这里)
.global _start
_start:
jmp do_call
jump_back:
xor %eax, %eax
xor %ebx, %ebx
xor %ecx, %ecx
xor %edx, %edx
movb $4, %al
movb $14, %dl
popl %ecx
movb $1, %bl
int $0x80
xor %eax, %eax
movb $1, %al
xor %ebx, %ebx
int $0x80
do_call:
call jump_back
hello:
.ascii "Hello, World!\n"
然后用as编译,
$ as hello.s -o hello.o
$ ld hello.o -o hello
然后用objdump得到机器码
$ objdump -d hello
08048054 <_start>:
8048054: eb 19 jmp 804806f <do_call>
08048056 <jump_back>:
8048056: 31 c0 xor %eax,%eax
8048058: 31 db xor %ebx,%ebx
804805a: 31 c9 xor %ecx,%ecx
804805c: 31 d2 xor %edx,%edx
804805e: b0 04 mov $0x4,%al
8048060: b2 0e mov $0xe,%dl
8048062: 59 pop %ecx
8048063: b3 01 mov $0x1,%bl
8048065: cd 80 int $0x80
8048067: 31 c0 xor %eax,%eax
8048069: b0 01 mov $0x1,%al
804806b: 31 db xor %ebx,%ebx
804806d: cd 80 int $0x80
0804806f <do_call>:
804806f: e8 e2 ff ff ff call 8048056 <jump_back>
08048074 <hello>:
8048074: 48 dec %eax
8048075: 65 gs
8048076: 6c insb (%dx),%es:(%edi)
8048077: 6c insb (%dx),%es:(%edi)
8048078: 6f outsl %ds:(%esi),(%dx)
8048079: 2c 20 sub $0x20,%al
804807b: 57 push %edi
804807c: 6f outsl %ds:(%esi),(%dx)
804807d: 72 6c jb 80480eb <hello+0x77>
804807f: 64 21 0a and %ecx,%fs:(%edx)
然后我把机器码串写来,写入文件hello_test.c
#include <stdlib.h>
char shellcode[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04"\
"\xb2\x0e\x59\xb3\x01\xcd\x80\x31\xc0\xb0\x01"\
"\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff"\
"\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c"\
"\x64\x21\x0a";
int main(int argc, char **argv) {
int (*ret)();
ret = (int(*)())shellcode;
(int)(*ret)();
exit(0);
}
然后编译
$ gcc -g hello_test.c -o hello_test
$ ./hello_test
Segmentation fault
怎么会出现这个错误啊
于是我看了一下
$ strace ./hello_test
(...)
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault
我实在不明白为什么会这样
于是我关掉了gcc 的stack保护,再编译
$ gcc -fno-stack-protector hello_test.c -o hello_test
$ ./hello_test
Segmentation fault
还是不行,晕了啊
有没有可以指点明路的高人
7 个解决方案
#1
#include <stdlib.h>
const unsigned char shellcode[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04"\
"\xb2\x0e\x59\xb3\x01\xcd\x80\x31\xc0\xb0\x01"\
"\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff"\
"\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c"\
"\x64\x21\x0a";
int main(int argc, char **argv) {
int (*ret)();
ret = (int(*)())shellcode;
(int)(*ret)();
exit(0);
}
#2
link的时候必须指明可执行栈
gcc参数加上 -z execstack
gcc参数加上 -z execstack
#3
非常感謝你的回复,重新试了一下,确实成功了
我试了几次,unsigned char 也不可以,一定要加上const
我在*上找到了可能我觉得正确的解释
http://*.com/questions/1576489/where-are-constant-variables-stored-in-c
一句话也就是加上const就把shellcode放到了 text section吧
#4
非常感謝nevil的回复,这个方法也让我的程序跑起来了
下面是一张图
shellcode在这里应该是被当做一个函数吧,有自己的stack
所以要加上execstack 选项
#5
对头,归根到底就是要让你这段shellcode所放的内存有执行的权限
#6
我也遇到这个问题了,明明返回地址已经覆盖成功了,eip里面已经是jmp esp的地址,esp里面已经是shellcode了,就是不能运行,加上-z execvestack可以了,哎,现在的系统为了对付缓冲区溢出也是煞费苦心啊。。。以后想靠溢出干啥的,恐怕是不再可行了吧
#7
more important: shellcode is for injection but who would disable overflow protection during compilation? no one...
#1
#include <stdlib.h>
const unsigned char shellcode[] = "\xeb\x19\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04"\
"\xb2\x0e\x59\xb3\x01\xcd\x80\x31\xc0\xb0\x01"\
"\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff"\
"\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c"\
"\x64\x21\x0a";
int main(int argc, char **argv) {
int (*ret)();
ret = (int(*)())shellcode;
(int)(*ret)();
exit(0);
}
#2
link的时候必须指明可执行栈
gcc参数加上 -z execstack
gcc参数加上 -z execstack
#3
非常感謝你的回复,重新试了一下,确实成功了
我试了几次,unsigned char 也不可以,一定要加上const
我在*上找到了可能我觉得正确的解释
http://*.com/questions/1576489/where-are-constant-variables-stored-in-c
一句话也就是加上const就把shellcode放到了 text section吧
#4
非常感謝nevil的回复,这个方法也让我的程序跑起来了
下面是一张图
shellcode在这里应该是被当做一个函数吧,有自己的stack
所以要加上execstack 选项
#5
对头,归根到底就是要让你这段shellcode所放的内存有执行的权限
#6
我也遇到这个问题了,明明返回地址已经覆盖成功了,eip里面已经是jmp esp的地址,esp里面已经是shellcode了,就是不能运行,加上-z execvestack可以了,哎,现在的系统为了对付缓冲区溢出也是煞费苦心啊。。。以后想靠溢出干啥的,恐怕是不再可行了吧
#7
more important: shellcode is for injection but who would disable overflow protection during compilation? no one...