C程序使用clang编译后,在我尝试修改汇编代码时导致zsh出现分段错误。

huangapple go评论134阅读模式
英文:

C program compiled file with clang leads to zsh: segmentation fault error when i try to change the assembly code

问题

I want to crack a simple C program password file by changing the assembly code with objdump.

I want to crack this C program by changing "jne" operation to "NOP" in objdump:

  1. int is_valid(const char* password)
  2. {
  3. if (strcmp(password, "MIOW") == 0) {
  4. return 1;
  5. } else {
  6. return 0;
  7. }
  8. }
  9. int main()
  10. {
  11. char* input = malloc(256);
  12. printf("What is the password? ");
  13. scanf("%s", input);
  14. if (is_valid(input)){
  15. printf("Correct! Go inside\n");
  16. } else {
  17. printf("Wrong.. you shall not enter!\n");
  18. }
  19. free(input);
  20. return 0;
  21. }

when I compile it with gcc and I try to change the "jne" to "nop" it works fine and when I type random characters as a password it says: "Correct! Go inside" but when I compile it with clang and then I change the "jne" to "nop", and when I run it and when I type some words as a password it gives "zsh: segmentation fault" error.

I modify the file when I compiled it with gcc with

  1. "printf "\x90\x90" | dd of=pass bs=1 seek=4525 count=2 conv=notrunc"

and when I compiled it with clang I modify it with

  1. "printf "\x90\x90" | dd of=pass bs=1 seek=4511 count=2 conv=notrunc"

I compile it with this command in my terminal

  1. clang Pass.c -o pass

and "jne" is available in both gcc and clang compiled file in "is_valid" function.

this is the assembly code that I get on the clang compiled file:

  1. 0000000000001180 <is_valid>:
  2. is_valid():
  3. 1180: 55 push %rbp
  4. 1181: 48 89 e5 mov %rsp,%rbp
  5. 1184: 48 83 ec 10 sub $0x10,%rsp
  6. 1188: 48 89 7d f0 mov %rdi,-0x10(%rbp)
  7. 118c: 48 8b 7d f0 mov -0x10(%rbp),%rdi
  8. 1190: 48 8d 35 6d 0e 00 00 lea 0xe6d(%rip),%rsi # 2004 <_IO_stdin_used+0x4>
  9. 1197: e8 b4 fe ff ff call 1050 <strcmp@plt>
  10. 119c: 83 f8 00 cmp $0x0,%eax
  11. 119f: 0f 85 0c 00 00 00 jne 11b1 <is_valid+0x31>
  12. 11a5: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp)
  13. 11ac: e9 07 00 00 00 jmp 11b8 <is_valid+0x38>
  14. 11b1: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
  15. 11b8: 8b 45 fc mov -0x4(%rbp),%eax
  16. 11bb: 48 83 c4 10 add $0x10,%rsp
  17. 11bf: 5d pop %rbp
  18. 11c0: c3 ret
  19. 11c1: 66 2e 0f 1f 84 00 00 00 00 00 cs nopw 0x0(%rax,%rax,1)
  20. 11cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)

and this is the assembly code from gcc compiler:

  1. 0000000000001189 <is_valid>:
  2. is_valid():
  3. 1189: 55 push %rbp
  4. 118a: 48 89 e5 mov %rsp,%rbp
  5. 118d: 48 83 ec 10 sub $0x10,%rsp
  6. 1191: 48 89 7d f8 mov %rdi,-0x8(%rbp)
  7. 1195: 48 8b 45 f8 mov -0x8(%rbp),%rax
  8. 1199: 48 8d 15 64 0e 00 00 lea 0xe64(%rip),%rdx # 2004 <_IO_stdin_used+0x4>
  9. 11a0: 48 89 d6 mov %rdx,%rsi
  10. 11a3: 48 89 c7 mov %rax,%rdi
  11. 11a6: e8 b5 fe ff ff call 1060 <strcmp@plt>
  12. 11ab: 85 c0 test %eax,%eax
  13. 11ad: 75 07 jne 11b6 <is_valid+0x2d>
  14. 11af: b8 01 00 00 00 mov $0x1,%eax
  15. 11b4: eb 05 jmp 11bb <is_valid+0x32>
  16. 11b6: b8 00 00 00 00 mov $0x0,%eax
  17. 11bb: c9 leave
  18. 11bc: c3 ret
英文:

I want to crack a simple C program password file by changing the assembly code with objdump
.

I want to crack this C program by changing "jne" operation to "NOP" in objdump:

  1. int is_valid(const char* password)
  2. {
  3. if (strcmp(password, &quot;MIOW&quot;) == 0) {
  4. return 1;
  5. } else {
  6. return 0;
  7. }
  8. }
  9. int main()
  10. {
  11. char* input = malloc(256);
  12. printf(&quot;What is the password? &quot; );
  13. scanf(&quot;%s&quot; , input);
  14. if (is_valid(input)){
  15. printf(&quot;Correct! Go inside\n&quot;);
  16. } else {
  17. printf(&quot;Wrong.. you shall not enter!\n&quot;);
  18. }
  19. free(input);
  20. return 0;
  21. }

when i compile it with gcc and i try to change the "jne" to "nop" it works fine and when i type random characters as password it says:"Correct! Go inside" but when i compile it with clang and then i change the "jne" to "nop" , and when i run it and when i type some words as password it gives "zsh: segmentation fault" error.


I modify the file when i compiled it with gcc with

  1. &quot;printf &quot;\x90\x90&quot; | dd of=pass bs=1 seek=4525 count=2 conv=notrunc&quot;

and when i compiled it with clang i modify it with

  1. &quot;printf &quot;\x90\x90&quot; | dd of=pass bs=1 seek=4511 count=2 conv=notrunc&quot;

i compile it with this command in my terminal

  1. clang Pass.c -o pass

and jne is available in both gcc and clang compiled file in "is_valid" function.


this is is the assembly code that i get on clang compiled file:

  1. 0000000000001180 &lt;is_valid&gt;:
  2. is_valid():
  3. 1180: 55 push %rbp
  4. 1181: 48 89 e5 mov %rsp,%rbp
  5. 1184: 48 83 ec 10 sub $0x10,%rsp
  6. 1188: 48 89 7d f0 mov %rdi,-0x10(%rbp)
  7. 118c: 48 8b 7d f0 mov -0x10(%rbp),%rdi
  8. 1190: 48 8d 35 6d 0e 00 00 lea 0xe6d(%rip),%rsi # 2004 &lt;_IO_stdin_used+0x4&gt;
  9. 1197: e8 b4 fe ff ff call 1050 &lt;strcmp@plt&gt;
  10. 119c: 83 f8 00 cmp $0x0,%eax
  11. 119f: 0f 85 0c 00 00 00 jne 11b1 &lt;is_valid+0x31&gt;
  12. 11a5: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp)
  13. 11ac: e9 07 00 00 00 jmp 11b8 &lt;is_valid+0x38&gt;
  14. 11b1: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
  15. 11b8: 8b 45 fc mov -0x4(%rbp),%eax
  16. 11bb: 48 83 c4 10 add $0x10,%rsp
  17. 11bf: 5d pop %rbp
  18. 11c0: c3 ret
  19. 11c1: 66 2e 0f 1f 84 00 00 00 00 00 cs nopw 0x0(%rax,%rax,1)
  20. 11cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)

and this is the assembly code from gcc complier:

  1. 0000000000001189 &lt;is_valid&gt;:
  2. is_valid():
  3. 1189: 55 push %rbp
  4. 118a: 48 89 e5 mov %rsp,%rbp
  5. 118d: 48 83 ec 10 sub $0x10,%rsp
  6. 1191: 48 89 7d f8 mov %rdi,-0x8(%rbp)
  7. 1195: 48 8b 45 f8 mov -0x8(%rbp),%rax
  8. 1199: 48 8d 15 64 0e 00 00 lea 0xe64(%rip),%rdx # 2004 &lt;_IO_stdin_used+0x4&gt;
  9. 11a0: 48 89 d6 mov %rdx,%rsi
  10. 11a3: 48 89 c7 mov %rax,%rdi
  11. 11a6: e8 b5 fe ff ff call 1060 &lt;strcmp@plt&gt;
  12. 11ab: 85 c0 test %eax,%eax
  13. 11ad: 75 07 jne 11b6 &lt;is_valid+0x2d&gt;
  14. 11af: b8 01 00 00 00 mov $0x1,%eax
  15. 11b4: eb 05 jmp 11bb &lt;is_valid+0x32&gt;
  16. 11b6: b8 00 00 00 00 mov $0x0,%eax
  17. 11bb: c9 leave
  18. 11bc: c3 ret

答案1

得分: 3

有两种不同的jne编码。请参考https://www.felixcloutier.com/x86/jcc。gcc使用“短”跳转JNE rel8,操作码为0x75,再加上一个字节的位移。而clang使用“近”编码,操作码为0x0f 0x85,再加上四个字节的位移。所以对于clang版本,你需要用0x90覆盖6个字节,而不是只有2个。你可以通过计算objdump输出指令的第二个字段中出现的字节数来直接验证这一点。

由于位移小于128字节,clang也可以使用短编码,这在代码大小方面更为高效。看起来这段代码是在没有进行优化的情况下编译的;如果进行了优化编译,短编码可能会被使用。

英文:

There are two different encodings of jne. See https://www.felixcloutier.com/x86/jcc. gcc is using the "short" jump JNE rel8, opcode 0x75 plus a one-byte displacement. clang is using the "near" encoding, opcode 0x0f 0x85 plus a four-byte displacement. So for the clang version, you need to overwrite 6 bytes with 0x90, instead of just 2. You can see this directly by counting the number of bytes appearing in the second field of the objdump output for the instruction.

Since the displacement is less than 128 bytes, clang could also be using the short encoding, which would be more efficient in terms of code size. It looks like this code was compiled without optimizations; if it were compiled with optimizations, the short encoding would probably be used instead.

huangapple
  • 本文由 发表于 2023年7月27日 19:13:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76779183.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定