英文:
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, "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 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
"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 is the assembly code that i get on 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 complier:
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
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论