How to unassemble x64 reset vector? - windows

I would like to see the first few instructions that my machine executes at startup. On x64 the reset vector is at physical address FFFFFFF0. I have enabled local kernel debugging on my Windows 10, restarted the PC and started WinDbg as Administrator. When doing a kernel debug (File -> Kernel Debug...), I am not sure what to type at the lkd> prompt to unassemble the code. I can do "!db FFFFFFF0" which displays some bytes:
#fffffff0 90 90 e9 83 e8 00 00 00-fc 00 00 00 00 00 e1 ff ................
#100000000 bb 00 fc 6a 00 00 e1 a9-00 00 bb 00 fc 6a 00 00 ...j.........j..
#100000010 01 aa 00 00 bb 00 fc 6a-00 00 21 aa 00 00 bb 00 .......j..!.....
#100000020 fc 6a 00 00 41 aa 00 00-bb 00 fc 6a 00 00 61 aa .j..A......j..a.
#100000030 00 00 bb 00 fc 6a 00 00-81 aa 00 00 bb 00 fc 6a .....j.........j
#100000040 00 00 a1 aa 00 00 bb 00-fc 6a 00 00 c1 aa 00 00 .........j......
#100000050 bb 00 fc 6a 00 00 e1 aa-00 00 bb 00 fc 6a 00 00 ...j.........j..
#100000060 01 ab 00 00 bb 00 fc 6a-00 00 21 ab 00 00 bb 00 .......j..!.....
then I tried "!u FFFFFFF0" which returns:
Op:
Dest:
Dest: 0
Src:
Srct: 0

it is just two nops and a jump if you mean you need to disassemble it as 16 bit
use ur
i patched the first 16 bytes from your query and disassemble it as 16 bit for demo below
0:000> db . l10
772805a6 90 90 e9 83 e8 00 00 00-fc 00 00 00 00 00 e1 ff ................
0:000> ur . l3
ntdll!LdrpDoDebuggerBreak+0x2c:
772805a6 90 nop
772805a7 90 nop
772805a8 e983e8 jmp EE2E
0:000>
Local Kernel Debugging is not Live it is Dead Debugging it operates on a snap shot
livekd operates on a state as the system was when dumped
!u is undocumented iirc and doesn't disassemble it provides a verbose details of a single instruction
0:000> u .+1 l1
ntdll!LdrpDoDebuggerBreak+0x2d:
772805a7 8975fc mov dword ptr [ebp-4],esi
0:000> !u 772805a7
Op: mov
Dest: esi
Dest: fffffffe
Src: dword ptr [ebp-4]
Srct: 0
0:000>
if you are looking for disassembling something like bios code use up
unassemble physical
kd> up cs:7c00 l1
0008:00007c00 eb52 jmp 00007c54
kd> up cs:7c54 l20
0008:00007c54 fa cli
0008:00007c55 33c0 xor eax,eax
0008:00007c57 8ed0 mov ss,ax
0008:00007c59 bc007cfb68 mov esp,68FB7C00h
0008:00007c5e c0071f rol byte ptr [edi],1Fh
0008:00007c61 1e push ds
0008:00007c62 686600cb88 push 88CB0066h
0008:00007c67 16 push ss
0008:00007c68 0e push cs
0008:00007c69 006681 add byte ptr [esi-7Fh],ah
0008:00007c6c 3e0300 add eax,dword ptr ds:[eax]
0008:00007c6f 4e dec esi
0008:00007c70 54 push esp
0008:00007c71 46 inc esi
0008:00007c72 53 push ebx
0008:00007c73 7515 jne 00007c8a
0008:00007c75 b441 mov ah,41h
0008:00007c77 bbaa55cd13 mov ebx,13CD55AAh
0008:00007c7c 720c jb 00007c8a
0008:00007c7e 81fb55aa7506 cmp ebx,675AA55h
0008:00007c84 f7c101007503 test ecx,3750001h
0008:00007c8a e9dd001e83 jmp 831e7d6c
i dont think debug.com is shipped in windows 10 x64 if you can get yourhands on win732bit etc you can use debug to disassemble the address
:>debug
-u f000:fff0 l1
F000:FFF0 EA5BE000F0 JMP F000:E05B
-u f000:e05b l1
F000:E05B EA3D3A00F0 JMP F000:3A3D
-u f000:3a3d l1
F000:3A3D FA CLI
-u f000:3a3d
F000:3A3D FA CLI
F000:3A3E B800F0 MOV AX,F000
F000:3A41 8ED0 MOV SS,AX
F000:3A43 BC493A MOV SP,3A49
F000:3A46 E93A8E JMP C883
F000:3A49 4B DEC BX
F000:3A4A 3ABB1DF1 CMP BH,[BP+DI+F11D]
F000:3A4E 2E CS:
F000:3A4F F747020800 TEST WORD PTR [BX+02],0008
F000:3A54 740E JZ 3A64
F000:3A56 32C0 XOR AL,AL
F000:3A58 BC5E3A MOV SP,3A5E
F000:3A5B E9E50B JMP 4643
-
I don't think you can step or disassemble the Physical Address f000:ffff in windbg.
I don't think it is mapped at all
I saw your post !db showing output so I wasn't quiet sure if it is available in x64.
afaik these codes are executed in Real Mode and you cant access them in protected mode with a software debugger like windbg
anyway back to the point
if you want to step through reset vector to MBR use a hardware emulator like bochs.
install bochs (2.6.11 x64 latest at the time of this edit) with the dlx demo
if you installed bochs in windows 10 you may need to give permissions to the bochs folder
(right click bochs folder->properties->security->edit full or write as the case may be)
once permission is granted you can double click the run.bat and you should land on LILo boot prompt
if you are here then close the bochs
open an elevated cmd prompt
and execute ../bochsdbg -f bochsrc
it will stop on Reset Vector
C:\Program Files\Bochs-2.6.11\dlxlinux>..\bochsdbg.exe -f ./bochsrc.bxrc
========================================================================
Bochs x86 Emulator 2.6.11
Built from SVN snapshot on January 5, 2020
Timestamp: Sun Jan 5 08:36:00 CET 2020
========================================================================
00000000000i[ ] reading configuration from ./bochsrc.bxrc
00000000000i[ ] installing win32 module as the Bochs GUI
00000000000i[ ] using log file bochsout.txt
Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
set a breakpoint at 0x7c00 using lb 0x7c00 (MBR START)
use s or n to step through
if you single step using s you may need to press s or ENTER 42.5 million times to reach MBR
here is a step through from reset vector to MBR using n or next
<bochs:5> blist
Num Type Disp Enb Address
1 lbreakpoint keep y 0x0000000000007c00
<bochs:6> u
00000000fffffff0: ( ): jmpf 0xf000:e05b ; ea5be000f0
<bochs:7> n
Next at t=1
(0) [0x0000000fe05b] f000:e05b (unk. ctxt): xor ax, ax ; 31c0
<bochs:8>
Next at t=2
(0) [0x0000000fe05d] f000:e05d (unk. ctxt): out 0x0d, al ; e60d
<bochs:9>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx cut off
Next at t=32
(0) [0x0000000fe0c4] f000:e0c4 (unk. ctxt): rep stosw word ptr es:[di], ax ; f3ab
<bochs:39>
Next at t=160
(0) [0x0000000fe0c6] f000:e0c6 (unk. ctxt): call .+13763 (0x000f168c) ; e8c335
<bochs:40>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx cut off
Next at t=5078
(0) [0x0000000fe0cf] f000:e0cf (unk. ctxt): mov word ptr ds:0x0413, ax ; a31304
<bochs:43>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx cut off
Next at t=330285
(0) [0x0000000fe1f5] f000:e1f5 (unk. ctxt): call .-18344 (0x000f9a50) ; e858b8
<bochs:146>
Next at t=1403926
(0) [0x0000000fe1f8] f000:e1f8 (unk. ctxt): mov cx, 0xc000 ; b900c0
<bochs:147>
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx cut off
Next at t=1877324
(0) [0x0000000fe21e] f000:e21e (unk. ctxt): call .+14565 (0x000f1b06) ; e8e538
<bochs:161>
Next at t=5333736
(0) [0x0000000fe221] f000:e221 (unk. ctxt): call .+21186 (0x000f34e6) ; e8c252
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx cut off
(0) [0x0000000fe230] f000:e230 (unk. ctxt): call .+12532 (0x000f1327) ; e8f430
<bochs:167>
Next at t=42311959
(0) [0x0000000fe233] f000:e233 (unk. ctxt): sti ; fb
<bochs:168>
Next at t=42311960
(0) [0x0000000fe234] f000:e234 (unk. ctxt): int 0x19 ; cd19
<bochs:169>
(0) Breakpoint 1, 0x0000000000007c00 in ?? () <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Next at t=42409977 <<<<< 42.5 million instructions until MBR is reached
(0) [0x000000007c00] 0000:7c00 (unk. ctxt): cli ; fa
<bochs:170> q
(0).[42409977] [0x000000007c00] 0000:7c00 (unk. ctxt): cli ; fa
Bochs is exiting. Press ENTER when you're ready to close this window.

Related

ELF file - get function of where a string is used

I have an elf file, and I would like to know if it's possible to get some infos about, where an variable (string) is used in the executable.
If I print out the strings of the .elf I find an interesting string, and I would like to know, in which function it is used, is this somehow possible?
Thank you!
Let's consider the following example:
test.c
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
char *str_a = "a";
char *str_abc = "abc";
printf("%s\n", str_a);
printf("%s\n", str_abc);
exit(EXIT_SUCCESS);
}
Let's compile it: gcc -Wall -pedantic-errors -o ~/test ~/test.c.
This will produce the file called test.
Let's examine .rodata section: readelf -x .rodata ./test.
This output is as follows:
Hex dump of section '.rodata':
0x00400610 01000200 61006162 6300 ....a.abc.
The starting address 0x00400610 is displayed. The four dots are displayed before the first string constant and thus the address of the string a will be 0x00400614. Skipping a and a null byte (delimiter) skips 2 bytes, and the address of abc will be 0x00400616.
So, at this point, the two addresses are known.
Next, let's perform objdump -M intel -d ./test.
Here is the listing of main within .text section:
0000000000400546 <main>:
400546: 55 push rbp
400547: 48 89 e5 mov rbp,rsp
40054a: 48 83 ec 20 sub rsp,0x20
40054e: 89 7d ec mov DWORD PTR [rbp-0x14],edi
400551: 48 89 75 e0 mov QWORD PTR [rbp-0x20],rsi
400555: 48 c7 45 f8 14 06 40 mov QWORD PTR [rbp-0x8],0x400614
40055c: 00
40055d: 48 c7 45 f0 16 06 40 mov QWORD PTR [rbp-0x10],0x400616
400564: 00
400565: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
400569: 48 89 c7 mov rdi,rax
40056c: e8 9f fe ff ff call 400410 <puts#plt>
400571: 48 8b 45 f0 mov rax,QWORD PTR [rbp-0x10]
400575: 48 89 c7 mov rdi,rax
400578: e8 93 fe ff ff call 400410 <puts#plt>
40057d: bf 00 00 00 00 mov edi,0x0
400582: e8 b9 fe ff ff call 400440 <exit#plt>
400587: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0]
40058e: 00 00
So, it is quite clear from the listing how the two strings are put on the screen. The listing mentions the two addresses found above - they are highlighted.
So, all in all, you may examine .rodata section, find the location address of a particular string and then just grep for the address found within .text section.

time attack on bash program with usleep() inside

I have a little hackme where I have to get the password with brute force. In the program is the function usleep(); when I have the right length and it is changing when one letter is right.
It would not be a problem, but the sleep time is about one minute and this is quite a long time.
Is there a way to make the usleep timer faster?
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs)
Method 1
You can override library functions with a LD_PRELOAD directive.
There's a good tutorial here and here to get you started with this.
Suppose you have the following program code, which is then compiled to a binary elf file.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for usleep() */
int main(int argc, char* argv[]) {
printf("Entry point. We'll now wait 10 seconds.\n");
system("date +\"%H:%M:%S\""); //Output time
usleep(10*1000*1000);
printf("Woke up again.\n");
system("date +\"%H:%M:%S\""); //Output time
return 0;
}
Running it normally would give you
root#kali:~/so# gcc -o prog prog.c
root#kali:~/so# ./prog
Entry point. We'll now wait 10 seconds.
20:31:10
Woke up again.
20:31:20
Now write your own version of usleep().
#include <unistd.h>
#include <stdio.h>
int usleep(useconds_t usec){
printf("Nope, you're not sleeping today :)\n");
return 0;
}
Compile it as a shared library.
root#kali:~/so# gcc -Wall -fPIC -shared -o usleep_override.so usleep_override.c
Now preload that library function before executing the original program.
root#kali:~/so# LD_PRELOAD=./usleep_override.so ./prog
Entry point. We'll now wait 10 seconds.
20:35:28
Nope, you're not sleeping today :)
Woke up again.
20:35:28
As you can see when looking at the date output, it executed the hooked function instead of the original and then immediatly returned.
Method 2
Modify the binary. In particular, modify the instructions sothat the usleep() function is not executed.
When we dump the instructions of the main() function of prog with objdump, we get:
root#kali:~/so# objdump -d -Mintel prog | grep -A20 "<main>"
0000000000400596 <main>:
400596: 55 push rbp
400597: 48 89 e5 mov rbp,rsp
40059a: 48 83 ec 10 sub rsp,0x10
40059e: 89 7d fc mov DWORD PTR [rbp-0x4],edi
4005a1: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi
4005a5: bf 68 06 40 00 mov edi,0x400668
4005aa: e8 a1 fe ff ff call 400450 <puts#plt>
4005af: bf 90 06 40 00 mov edi,0x400690
4005b4: e8 a7 fe ff ff call 400460 <system#plt>
4005b9: bf 80 96 98 00 mov edi,0x989680
4005be: e8 cd fe ff ff call 400490 <usleep#plt>
4005c3: bf a2 06 40 00 mov edi,0x4006a2
4005c8: e8 83 fe ff ff call 400450 <puts#plt>
4005cd: bf 90 06 40 00 mov edi,0x400690
4005d2: e8 89 fe ff ff call 400460 <system#plt>
4005d7: b8 00 00 00 00 mov eax,0x0
4005dc: c9 leave
4005dd: c3 ret
4005de: 66 90 xchg ax,ax
We can see the offending lines that are responsible for the usleep(10*1000*1000) call:
4005b9: bf 80 96 98 00 mov edi,0x989680
4005be: e8 cd fe ff ff call 400490 <usleep#plt>
Since 0x989680 equals 10000000 in decimal, we can deduce that this is the argument for the usleep() function. So, we can just modify the binary (search for the byte sequence bf 80 96 98 00 e8 cd fe ff ff) and instead just put the 0x90 there for a NOP instruction, which does nothing.
Before and after:
When we now dump the instructions:
root#kali:~/so# objdump -d -Mintel prog_cracked | grep -A28 "<main>"
0000000000400596 <main>:
400596: 55 push rbp
400597: 48 89 e5 mov rbp,rsp
40059a: 48 83 ec 10 sub rsp,0x10
40059e: 89 7d fc mov DWORD PTR [rbp-0x4],edi
4005a1: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi
4005a5: bf 68 06 40 00 mov edi,0x400668
4005aa: e8 a1 fe ff ff call 400450 <puts#plt>
4005af: bf 90 06 40 00 mov edi,0x400690
4005b4: e8 a7 fe ff ff call 400460 <system#plt>
4005b9: 90 nop
4005ba: 90 nop
4005bb: 90 nop
4005bc: 90 nop
4005bd: 90 nop
4005be: 90 nop
4005bf: 90 nop
4005c0: 90 nop
4005c1: 90 nop
4005c2: 90 nop
4005c3: bf a2 06 40 00 mov edi,0x4006a2
4005c8: e8 83 fe ff ff call 400450 <puts#plt>
4005cd: bf 90 06 40 00 mov edi,0x400690
4005d2: e8 89 fe ff ff call 400460 <system#plt>
4005d7: b8 00 00 00 00 mov eax,0x0
4005dc: c9 leave
4005dd: c3 ret
4005de: 66 90 xchg ax,ax
Nice, the call is gone. Run and we get:
root#kali:~/so# chmod +x prog_cracked
root#kali:~/so# ./prog_cracked
Entry point. We'll now wait 10 seconds.
21:11:18
Woke up again.
21:11:18
And thus, the program is "cracked" again.

je to jne in assembly

I am disassembling a code which has the following je function:
0F 84 FF 00 00 00 : je loc_00000105
I am instructed to bypass the compare function by modifying je to jne. This is a weird case because everywhere i experienced this:
74 F1 : jne loc_fffffff3
Which i can easily change by changing 74 to 75:
75 F1 : jne loc_fffffff3
But i am really confused how can i change:
0F 84 FF 00 00 00 : je loc_00000105 to jne
Any help will be appreciated!
I tried Changing :
0F to 0E
0F to 0B
etc...
Here is a nice x86 instruction set reference for you:
http://ref.x86asm.net/coder32.html
The 74 XX and 75 XX instruction encodings are JE and JNE with a 8-bit relative offset for the jump target.
0F 85 XX XX XX XX is the instruction encoding for JNE with a 32 bit offset that follows .
The corresponding JE instruction is 0F 84 XX XX XX XX.
74 is the x86 short je opcode, and 0F 84 is the near je opcode.
So this je -> jne short jump opcode patch:
74 -> 75
Would be equivalent to these je -> jne near jump opcodes.
0F 84 -> 0F 85
Here are some opcode tables for reference:
x86: http://ref.x86asm.net/coder32.html
x86_64: http://ref.x86asm.net/coder64.html

GDB and opcodes

Coming from a Windows environment, when I do kernel debugging or even in user mode for that matter, I can see the disassembled code in a way that is quite detailed, for example:
80526db2 6824020000 push 224h
80526db7 6808a14d80 push offset nt!ObWatchHandles+0x8dc (804da108)
80526dbc e81f030100 call nt!_SEH_prolog (805370e0)
80526dc1 a140a05480 mov eax,dword ptr [nt!__security_cookie (8054a040)]
The first number is the address quite obviously but the second represent the opcode bytes and that is lacking on GDB or at least, I don't know how to get a similar result.
I usually will do something like this:
(gdb): display /i $pc
But all I get is something like this:
x/i $pc 0x21c4c: pop %eax
I can see what the code bytes are which is sometimes a bit of an issue for me. Is there something I can do with display that could help?
Edit: GDB in question is 6.3.50 on Mac OS X 10.8.3.
I think disassemble /r should give you what you are looking for:
(gdb) help disass
Disassemble a specified section of memory.
Default is the function surrounding the pc of the selected frame.
With a /m modifier, source lines are included (if available).
With a /r modifier, raw instructions in hex are included.
With a single argument, the function surrounding that address is dumped.
Two arguments (separated by a comma) are taken as a range of memory to dump,
in the form of "start,end", or "start,+length".
(gdb) disass /r main
Dump of assembler code for function main:
0x004004f8 <+0>: 55 push %ebp
0x004004f9 <+1>: 48 dec %eax
0x004004fa <+2>: 89 e5 mov %esp,%ebp
0x004004fc <+4>: 48 dec %eax
0x004004fd <+5>: 83 ec 10 sub $0x10,%esp
0x00400500 <+8>: 89 7d fc mov %edi,-0x4(%ebp)
0x00400503 <+11>: 48 dec %eax
0x00400504 <+12>: 89 75 f0 mov %esi,-0x10(%ebp)
0x00400507 <+15>: bf 0c 06 40 00 mov $0x40060c,%edi
0x0040050c <+20>: b8 00 00 00 00 mov $0x0,%eax
0x00400511 <+25>: e8 0a ff ff ff call 0x400420
0x00400516 <+30>: bf 00 00 00 00 mov $0x0,%edi
0x0040051b <+35>: e8 10 ff ff ff call 0x400430
End of assembler dump.
(gdb)
GDB disassemble command documentation
If you use lldb, you can use the -b option to disassemble to get the same effect:
(lldb) disassemble -b -p
Sketch`main + 46 at SKTMain.m:17:
-> 0x10001aa0e: 48 89 c7 movq %rax, %rdi
0x10001aa11: b0 00 movb $0, %al
0x10001aa13: e8 f2 48 00 00 callq 0x10001f30a ; symbol stub for: NSLog
0x10001aa18: 48 8d 35 99 fa 00 00 leaq 64153(%rip), %rsi ; #Sketch`.str3

how to generate a map of instructions when compiling?

when compiling a program with gcc or any other compiler, can I somehow make the compiler generate a map of instructions in memory ??
something like:
0000: First Instruction
0001: Second Instruction
1000: Third Instruction (after a jump for example)
I would like to use these addresses as a pattern to test a design of an instruction cache. I don't care what instructions are compiled or anything like that, just the addresses of these instruction. is this possible?
The easiest way has to be to use objdump on your compiled output. For instance:
$ objdump -d /tmp/test
/tmp/test: file format elf64-x86-64
Disassembly of section .text:
0000000000400410 <_start>:
400410: 31 ed xor %ebp,%ebp
400412: 49 89 d1 mov %rdx,%r9
400415: 5e pop %rsi
400416: 48 89 e2 mov %rsp,%rdx
400419: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40041d: 50 push %rax
40041e: 54 push %rsp
40041f: 49 c7 c0 b0 05 40 00 mov $0x4005b0,%r8
400426: 48 c7 c1 20 05 40 00 mov $0x400520,%rcx
40042d: 48 c7 c7 fa 04 40 00 mov $0x4004fa,%rdi
400434: e8 b7 ff ff ff callq 4003f0 <__libc_start_main#plt>
400439: f4 hlt
40043a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
And so on. If you want to only have the addresses, just filter them out with sed or something.

Resources