-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from burhanr13/more-examples
more examples
- Loading branch information
Showing
10 changed files
with
239 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# InsertInstructionPath | ||
|
||
We have a simple C program: | ||
|
||
```c title="examples/insert_instruction_patch/add.c" | ||
--8<-- "examples/insert_instruction_patch/add.c" | ||
``` | ||
|
||
And here is the disassembly of the compiled binary: | ||
|
||
```asm title="examples/insert_instruction_patch/add" | ||
0000000000001149 <add>: | ||
1149: f3 0f 1e fa endbr64 | ||
114d: 55 push %rbp | ||
114e: 48 89 e5 mov %rsp,%rbp | ||
1151: 89 7d fc mov %edi,-0x4(%rbp) | ||
1154: 89 75 f8 mov %esi,-0x8(%rbp) | ||
1157: 8b 55 fc mov -0x4(%rbp),%edx | ||
115a: 8b 45 f8 mov -0x8(%rbp),%eax | ||
115d: 01 d0 add %edx,%eax | ||
115f: 5d pop %rbp | ||
1160: c3 ret | ||
0000000000001161 <main>: | ||
1161: f3 0f 1e fa endbr64 | ||
1165: 55 push %rbp | ||
1166: 48 89 e5 mov %rsp,%rbp | ||
1169: be 03 00 00 00 mov $0x3,%esi | ||
116e: bf 02 00 00 00 mov $0x2,%edi | ||
1173: e8 d1 ff ff ff call 1149 <add> | ||
1178: 89 c6 mov %eax,%esi | ||
117a: 48 8d 05 83 0e 00 00 lea 0xe83(%rip),%rax # 2004 <_IO_stdin_used+0x4> | ||
1181: 48 89 c7 mov %rax,%rdi | ||
1184: b8 00 00 00 00 mov $0x0,%eax | ||
1189: e8 c2 fe ff ff call 1050 <printf@plt> | ||
118e: b8 00 00 00 00 mov $0x0,%eax | ||
1193: 5d pop %rbp | ||
1194: c3 ret | ||
``` | ||
|
||
Suppose we want to modify the add function to do some | ||
extra calculations on the first argument, for example doubling it and adding 5, without changing the rest of the | ||
function. We can use Patcherex2's `InsertInstructionPatch` | ||
to insert these instructions at the address `114d` which is | ||
at the beginning of the function. To insert instructions, we | ||
need at least enough space to fit a jump instruction | ||
before the function ends, so we cannot insert them | ||
later on in the function. | ||
Here is how: | ||
|
||
```python title="examples/insert_instruction_patch/patch.py" | ||
--8<-- "examples/insert_instruction_patch/patch.py" | ||
``` | ||
|
||
Now we can run this script and run the patched binary | ||
to see the result: | ||
|
||
```bash | ||
$ ./add.patched | ||
2 + 3 = 12 | ||
``` | ||
|
||
We have successfully modified the binary at the | ||
instruction level. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Multiple Patches | ||
|
||
Here is a simple example of a vulnerable C program which we will use to show how different patches can be used together: | ||
|
||
```c title = "examples/multiple_patches/getline.c" | ||
--8<-- "examples/multiple_patches/getline.c" | ||
``` | ||
|
||
And here is the disassembly of the relevant functions: | ||
|
||
```asm title = "examples/multiple_patches/getline" | ||
0000000000001189 <my_getline>: | ||
1189: f3 0f 1e fa endbr64 | ||
118d: 55 push %rbp | ||
118e: 48 89 e5 mov %rsp,%rbp | ||
1191: 48 83 ec 20 sub $0x20,%rsp | ||
1195: 48 89 7d e8 mov %rdi,-0x18(%rbp) | ||
1199: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) | ||
11a0: 48 8b 05 69 2e 00 00 mov 0x2e69(%rip),%rax # 4010 <stdin@GLIBC_2.2.5> | ||
11a7: 48 89 c7 mov %rax,%rdi | ||
11aa: e8 e1 fe ff ff call 1090 <getc@plt> | ||
11af: 88 45 fb mov %al,-0x5(%rbp) | ||
11b2: 80 7d fb 0a cmpb $0xa,-0x5(%rbp) | ||
11b6: 74 1b je 11d3 <my_getline+0x4a> | ||
11b8: 8b 45 fc mov -0x4(%rbp),%eax | ||
11bb: 8d 50 01 lea 0x1(%rax),%edx | ||
11be: 89 55 fc mov %edx,-0x4(%rbp) | ||
11c1: 48 63 d0 movslq %eax,%rdx | ||
11c4: 48 8b 45 e8 mov -0x18(%rbp),%rax | ||
11c8: 48 01 c2 add %rax,%rdx | ||
11cb: 0f b6 45 fb movzbl -0x5(%rbp),%eax | ||
11cf: 88 02 mov %al,(%rdx) | ||
11d1: eb cd jmp 11a0 <my_getline+0x17> | ||
11d3: 90 nop | ||
11d4: 8b 45 fc mov -0x4(%rbp),%eax | ||
11d7: 48 63 d0 movslq %eax,%rdx | ||
11da: 48 8b 45 e8 mov -0x18(%rbp),%rax | ||
11de: 48 01 d0 add %rdx,%rax | ||
11e1: c6 00 00 movb $0x0,(%rax) | ||
11e4: 8b 45 fc mov -0x4(%rbp),%eax | ||
11e7: c9 leave | ||
11e8: c3 ret | ||
00000000000011e9 <main>: | ||
11e9: f3 0f 1e fa endbr64 | ||
11ed: 55 push %rbp | ||
11ee: 48 89 e5 mov %rsp,%rbp | ||
11f1: 48 83 ec 20 sub $0x20,%rsp | ||
11f5: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax | ||
11fc: 00 00 | ||
11fe: 48 89 45 f8 mov %rax,-0x8(%rbp) | ||
1202: 31 c0 xor %eax,%eax | ||
1204: 48 8d 45 ee lea -0x12(%rbp),%rax | ||
1208: 48 89 c7 mov %rax,%rdi | ||
120b: e8 79 ff ff ff call 1189 <my_getline> | ||
1210: 48 8d 45 ee lea -0x12(%rbp),%rax | ||
1214: 48 89 c7 mov %rax,%rdi | ||
1217: e8 54 fe ff ff call 1070 <puts@plt> | ||
121c: b8 00 00 00 00 mov $0x0,%eax | ||
1221: 48 8b 55 f8 mov -0x8(%rbp),%rdx | ||
1225: 64 48 2b 14 25 28 00 sub %fs:0x28,%rdx | ||
122c: 00 00 | ||
122e: 74 05 je 1235 <main+0x4c> | ||
1230: e8 4b fe ff ff call 1080 <__stack_chk_fail@plt> | ||
1235: c9 leave | ||
1236: c3 ret | ||
``` | ||
|
||
The program currently reads a string from standard input and echos it back. We can run it with short strings: | ||
```bash | ||
$ ./getline | ||
aaaaa | ||
aaaaa | ||
``` | ||
And it works fine. Using a longer string, however will cause it to crash: | ||
```bash | ||
$ ./getline | ||
aaaaaaaaaaaaaaaaaaa | ||
aaaaaaaaaaaaaaaaaaa | ||
*** stack smashing detected ***: terminated | ||
[1] 194473 IOT instruction (core dumped) ./getline | ||
``` | ||
|
||
We will patch this program to fix the vulnerability, by adding a second argument to the `my_getline` function, and printing a message when the buffer would have overflowed. Here is the script: | ||
|
||
```python title = "examples/multiple_patches/patch.py" | ||
--8<-- "examples/multiple_patches/patch.py" | ||
``` | ||
|
||
This patch adds the buffer size as a second argument to `my_getline`. To do this we insert instructions at the beginning to save the argument, and in the loop body we insert a check to see if the index is out of bounds. When it is, we print a message, which was inserted using the `InsertDataPatch`. We can use the `SAVE_CONTEXT` and `RESTORE_CONTEXT` macros (expanded by Patcherex2) to do operations that could modify data we have in registers, like calling a function. We also insert instructions in `main` to put the buffer size in `esi` before calling the function. Now we can run the script to patch the binary and run the new fixed program: | ||
```bash | ||
$ ./getline.patched | ||
aaaaaaaaaaaaaaaaaaaaaaa | ||
Ran out of space | ||
aaaaaaaaa | ||
``` | ||
|
||
We have successfully fixed the bug with Patcherex2. |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include <stdio.h> | ||
|
||
int add(int a, int b) { | ||
return a + b; | ||
} | ||
|
||
int main() { | ||
printf("2 + 3 = %d\n", add(2, 3)); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from patcherex2 import * | ||
|
||
p = Patcherex("add") | ||
|
||
|
||
asm_str = """ | ||
add edi, edi | ||
add edi, 5 | ||
""" | ||
|
||
p.patches.append(InsertInstructionPatch(0x114d,asm_str)) | ||
p.apply_patches() | ||
|
||
p.binfmt_tool.save_binary() |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#include <stdio.h> | ||
|
||
int my_getline(char* buf) { | ||
int i = 0; | ||
while (1) { | ||
char c = getc(stdin); | ||
if (c == '\n') break; | ||
buf[i++] = c; | ||
} | ||
buf[i] = '\0'; | ||
return i; | ||
} | ||
|
||
int main() { | ||
|
||
char buf[10]; | ||
my_getline(buf); | ||
puts(buf); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from patcherex2 import * | ||
|
||
p = Patcherex("getline") | ||
|
||
p.patches.append(InsertInstructionPatch(0x120b,"mov esi, 0xa\n")) | ||
p.patches.append(InsertDataPatch("my_str",b"Ran out of space\0")) | ||
|
||
p.patches.append(InsertInstructionPatch(0x1199,"mov [rbp-0xc],esi")) | ||
|
||
asm_string = """ | ||
cmp edx, [rbp-0xc] | ||
jl less | ||
SAVE_CONTEXT | ||
lea rdi, [{my_str}] | ||
call {puts} | ||
RESTORE_CONTEXT | ||
mov rsi, [rbp-0x18] | ||
mov byte ptr [rsi+rax], 0 | ||
mov eax, edx | ||
leave | ||
ret | ||
less: | ||
""" | ||
|
||
p.patches.append(InsertInstructionPatch(0x11c1,asm_string)) | ||
|
||
p.apply_patches() | ||
|
||
p.binfmt_tool.save_binary() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters