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

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

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:


int is_valid(const char* password)
{
    if (strcmp(password, "MIOW") == 0) {
        return 1;
    }   else {
        return 0;
    }
}

int main()
{
    char* input = malloc(256);

    printf("What is the password? ");
    scanf("%s", input);

    if (is_valid(input)){
        printf("Correct! Go inside\n");
    } else {
        printf("Wrong.. you shall not enter!\n");
    }

    free(input);
    return 0;
}

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

"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

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

I compile it with this command in my terminal

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:

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

and this is the assembly code from gcc compiler:

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


int is_valid(const char* password)
    {
        if (strcmp(password, &quot;MIOW&quot;) == 0) {
            return 1;
        }   else {
            return 0;
        }
    }

    int main()
    {
        char* input = malloc(256);

        printf(&quot;What is the password? &quot; );
        scanf(&quot;%s&quot; , input);

        if (is_valid(input)){
            printf(&quot;Correct! Go inside\n&quot;);
        } else {
            printf(&quot;Wrong.. you shall not enter!\n&quot;);
        }

        free(input);
        return 0;
    }


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

&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

&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

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:

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

and this is the assembly code from gcc complier:

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

确定