我在使用jmp时出现了分段错误。
第一次,我只使用了jmp 0x30,就出现了分割错误。
我用gdb调试了我的程序,我看到在调用jmp之后,它跳到了一个绝对地址。

(gdb) b main
Breakpoint 1 at 0x80483b7: file f.c, line 3.
(gdb) r
Starting program: /root/work/f

Breakpoint 1, main () at f.c:3
3       __asm__("jmp 0x30\n"
(gdb) n
0x00000030 in ?? ()
(gdb)

我想它也可能是一个相对地址,所以我修改了jmp的参数作为call的地址。
就像这样,
#include<stdio.h>
int main(){
__asm__("jmp 0x080483e6\n"
"popl %esi\n"
"movl %esi,0x8(%esi)\n"
"movb $0x0,0x7(%esi)\n"
"movl $0x0,0xc(%esi)\n"
"movl $0xb,%eax\n"
"movl %esi,%ebx\n"
"leal 0x8(%esi),%ecx\n"
"leal 0xc(%esi),%edx\n"
"int $0x80\n"
"movl $0x1, %eax\n"
"movl $0x0, %ebx\n"
"int $0x80\n"
"call 0x2a\n"
".string \"/bin/sh\"\n");
return 0;
}

但我知道了
Breakpoint 1, main () at f.c:3
3       __asm__("jmp 0x080483e6\n"
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x0000002a in ?? ()
(gdb)

我发现了这个相关的问题,我就这样修改了代码。
#include<stdio.h>
int main(){
__asm__("jmp L\n"
"sub:\n"
"popl %esi\n"
"movl %esi,0x8(%esi)\n"
"movb $0x0,0x7(%esi)\n"
"movl $0x0,0xc(%esi)\n"
"movl $0xb,%eax\n"
"movl %esi,%ebx\n"
"leal 0x8(%esi),%ecx\n"
"leal 0xc(%esi),%edx\n"
"int $0x80\n"
"movl $0x1, %eax\n"
"movl $0x0, %ebx\n"
"int $0x80\n"
"jmp exit\n"
"L:\n"
"call sub\n"
".string \"/bin/sh\"\n"
"exit:\n");
return 0;
}

但它不适合我,在调用disassemble main之后,指令地址仍然是jmp的行
(gdb) b main
Breakpoint 1 at 0x80483b7: file f.c, line 3.
(gdb) r
Starting program: /root/work/f

Breakpoint 1, main () at f.c:3
3       __asm__("jmp L\n"
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x080483ba in main () at f.c:3
3       __asm__("jmp L\n"
(gdb) n

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb)

我不知道问题在哪里,我真的很感谢你的帮助!

最佳答案

我不认为分段错误是由jmp L指令引起的。
看看我在这里做了什么:

(gdb) b main
Breakpoint 1 at 0x80483be: file test.c, line 3.
(gdb) run
Starting program: /home/cad/a.out

Breakpoint 1, main () at test.c:3
3       __asm__("jmp L\n"
(gdb) display/i $pc
1: x/i $pc
=> 0x80483be <main+3>:  jmp    0x80483ec <main+49>
(gdb) si
0x080483ec      3       __asm__("jmp L\n"
1: x/i $pc
=> 0x80483ec <main+49>: call   0x80483c0 <main+5>
(gdb) si
0x080483c0      3       __asm__("jmp L\n"
1: x/i $pc
=> 0x80483c0 <main+5>:  pop    %esi
(gdb) si
0x080483c1      3       __asm__("jmp L\n"
1: x/i $pc
=> 0x80483c1 <main+6>:  mov    %esi,0x8(%esi)
(gdb) si

Program received signal SIGSEGV, Segmentation fault.
0x080483c1 in main () at test.c:3
3       __asm__("jmp L\n"
1: x/i $pc
=> 0x80483c1 <main+6>:  mov    %esi,0x8(%esi)
(gdb)

如您所见,我在main处设置了一个断点,并启用了对每个执行的机器指令的反汇编(display/i $pc)然后,我浏览了机器指令(si)结果发现,错误指令是mov %esi,0x8(%esi)at0x80483c1
据我所知,问题是gdb只显示它执行的下一个完整语句由于一条语句以分号结尾,只要调试器遍历__asm__("...")语句,整个__asm__("jmp L\n"语句就算作一条语句,gdb只打印它的第一行,即__asm__
所以我们把它弄清楚了,现在让我们找出导致分割错误的原因。
当您跳到L时,将执行call sub这会将32位返回地址推送到堆栈上subpop %esi中的第一条指令用返回地址填充%esi,并将其从堆栈中移除。
当您现在执行mov %esi,0x8(%esi)操作时,CPU会尝试将%esi移动到0x8字节后面的返回地址点,即在代码段内而且,看起来,代码在操作系统上是只读的,所以程序会出错。

关于c - 调用jmp时,C内联汇编出现段错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39685490/

10-11 19:07