Forgot to mention my thanks for the example and clearing up my understanding of where the offset begins from
Forgot to mention my thanks for the example and clearing up my understanding of where the offset begins from
I see you struggling with the opcodes, I'd suggest using this website as a reference:
coder64 edition | X86 Opcode and Instruction Reference 1.12
It was extremely useful to me when I was trying to compile my own x86 bootstrapper. Compiling by hand... omg, it's difficult.
Devoted my life to programming...
Yeah I already found that reference but it's not exactly clear about the bytes that come after the instruction, for example some say they expect an immediate 16 or 32 byte value, but how does one tell it which to expect and where to send it? I managed barely to understand that the 1st 4 bits of an M byte indicate which register to send it to but what about the last 4 bits, what do they represent? The bitwise struct I posted earlier showes what I thought it was judging by the bytes I copied and that very reference, but a reference without links to examples is only useful if you already know how to use the bytes in question
Well, not all instructions follow that simple pattern. Most of the legacy (1-byte opcode) ones do, but then you have 1-byte "opcode+register" instructions, and 2-byte ones follow an entirely different pattern, not to mention abominations such as 3Dnow! that append the opcode as an immediate at the end!!! That is why I quit trying to recognize pattern in the opcodes and only concern myself with the standard bitfields, I mean the ModRM and SIB ones.
Remember that what determines the immediate size are the opcode itself plus any operand-size prefix plus the current CPU mode. For example, "0xB0" is always "mov al, imm8" but "0xB8" can be any of the other three "mov ax/eax/rax, imm16/32/64".
Devoted my life to programming...
Sure. The following are for long mode:
x86-64 cannibalized the 1-byte INC and DEC instructions to define the REX prefixes. Here, 0x48 is REX.W, which makes the processor use 64-bit operands.Code:0x66 0xB9 0x34 0x12 ; mov cx, 0x1234 0xB9 0x34 0x12 0x00 0x00 ; mov ecx, 0x1234 0x48 0xB9 0x34 0x12 0x00 0x00 0x00 0x00 0x00 0x00 ; mov rcx, 0x1234
Last edited by GReaper; 04-13-2019 at 11:17 AM.
Devoted my life to programming...
LEA is complicated (in long mode, anything accessing memory is complicated, really...), so I'll just show you examples for 32-bit mode:
In long mode, you no longer have access to 16-bit addressing. Rather, 64-bit is the default and 0x67 changes to 32-bit.Code:0x67 0x66 0x8D 0x45 0x0C ; lea ax, [di+12] ; 0x67 0x8D 0x45 0x0C ; lea eax, [di+12] ; 16-bit addressing 0x66 0x8D 0x47 0x0C ; lea ax, [edi+12] ; 0x8D 0x47 0x0C ; lea eax, [edi+12] ; 32-bit addressing ; Here are some examples with the 32-bit SIB byte 0x8D 0x04 0x7D 0x00 0xC0 0x07 0x00 ; lea eax, [edi*2 + 0x7C000] 0x8D 0x0C 0x82 ; lea ecx, [eax*4+edx]
EDIT: Now that I think about it though, the 64-bit ModRM and SIB bytes behave identically to the 32-bit ones, assuming the upper 32 bits of the operands are cleared and no REX prefixes are present. So, the 32-bit examples I gave above, in long mode are:
Code:; Same exact binary values lea ax, [rdi+12] ; lea eax, [rdi+12] ; 64-bit addressing lea eax, [rdi*2 + 0x7C000] lea ecx, [rax*4+rdx]
Last edited by GReaper; 04-14-2019 at 09:30 AM.
Devoted my life to programming...
Okay still struggling, here's the produced elf I'm trying to get running:
test.elf - Google Drive
The section of code that initialises _start() & main()
And the output of readelf:Code:start_t begin__start = { /* mov edi,DWORD PTR [rsp] #Move argc into param1 register */ { 0x8B, 0x3C, 0x24}, /* lea rsi,[rsp+0x8] #Move argv into param2 register */ { 0x48, 0x8D, 0x74, 0x24, 0x08 }, /* call main() */ { 0xE8, (2 + sizeof(syscall_t)) }, /* mov edi,eax #Move result of main() into param1 register */ { 0x89, 0xC7 }, { /* mov eax,id? of exit() #Set exit() for syscall instruction */ { 0xB8, __NR_exit }, /* syscall */ 0x50F } }; main_t begin_main = { #ifdef USE_STACK /* push rbp */ { 0x48, 0x55 }, /* mov rbp,rsp */ { 0x48, 0x89, 0xE5 }, #endif /* mov eax,0x00000000 */ { 0xB8, 0 }, #ifdef USE_STACK /* pop rbp */ { 0x48, 0x5D }, #endif /* ret */ 0xC3 };
Any ideas? I get the feeling that perhaps the problem is not in the executable bytes but how I'm declaring them since I outright copied some from a sample elf that was forced to bare minimum at the start which is how I got the argc/argv stuff and the setup of the exit() call, the only thing I actually modified to begin with was the call to main()'s relative address because it was no longer valid where it was referencing.Code:readelf -all test.elf ELF Header: Magic: 7f 45 4c 46 02 01 01 ff 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: <unknown: ff> ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x298 Start of program headers: 64 (bytes into file) Start of section headers: 176 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 2 Size of section headers: 64 (bytes) Number of section headers: 4 Section header string table index: 1 readelf: Warning: Section 2 has an out of range sh_info value of 7 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .shstrtab STRTAB 00000000000001b0 000001b0 0000000000000040 0000000000000001 AS 0 0 1 [ 2] .symtab SYMTAB 00000000000001f0 000001f0 00000000000000a8 0000000000000018 WAI 1 7 8 [ 3] .text PROGBITS 0000000000000298 00000298 000000000000001c 0000000000000001 WAXlp 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0 LOAD 0x0000000000000000 0x0000000000000298 0x0000000000000298 0x000000000000001c 0x000000000000001c RWE 0x0 Section to Segment mapping: Segment Sections... 00 01 There is no dynamic section in this file. There are no relocations in this file. The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.symtab' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000000001b0 64 SECTION LOCAL DEFAULT 1 .shstrtab 2: 00000000000001f0 168 SECTION LOCAL DEFAULT 2 .symtab 3: 0000000000000298 28 SECTION LOCAL DEFAULT 3 .text 4: 0000000000000298 28 FILE LOCAL DEFAULT ABS mitsy.c 5: 0000000000000298 22 NOTYPE GLOBAL DEFAULT 3 _start 6: 00000000000002ae 6 FUNC GLOBAL DEFAULT 3 main No version information found in this file.
That may not be the problem, but I see you use "0x48" with push and pop. I don't think that's right, because in long mode you can only push and pop 64-bit registers (the instruction defaults to it).
EDIT: Oh, I just realized. Your mov instruction is wrong. If you want to use an immediate, it should be 5 bytes, not 2 (since the immediate is 32-bit).
Last edited by GReaper; 04-15-2019 at 07:04 AM.
Devoted my life to programming...
Ahh kk thx, I put those in thinking it would upgrade from ebp to rbp as a result, since they're not needed then I'll just remove them then.
Edit: lol I must've caught your message before it was modified when re-loading but caught the modified when quoting, that mov is actually declared via a struct now hence only 2 integers:
Code:typedef struct ATTR_PACKED { u8 x; u32 s; } x8s32_t;
Last edited by awsdert; 04-15-2019 at 07:10 AM.
Here's my current code with the elfs I was referencing:
mitsy.tar.gz - Google Drive
If ya'll are wandering what the progress is it's zilch, since I couldn't think of how to fix the execution problem I decided to first redesign my code to no longer require fixed positions when building the elf headers, so far as a means of managing memory I have each be built in temporary files while sharing a buffer for reading/writing each header, the next part I'm doing now is translating my old code to the new code and build the same file using the new code, when that's done I'll circle back to the execution issue by trying to replicate ALL the various headers/data seen in the example.elf and sample.elf I created with gcc instead of just what I thought was needed, once done if it still fails to execute then I'll know it's the byte code and not missing information that's the issue.
Well, I've finished making my code more portable in nature, still getting execution errors though, gonna go sleep now, maybe someone will notice something I overlooked while I'm doing that. Here's my output:
Code:make check (in directory: /home/zxuiji/Desktop/mitsy) sys=Linux cpu=x86_64 ./mitsy.elf cd ./gede-2.14.1 && make make[1]: Entering directory '/home/zxuiji/Desktop/mitsy/gede-2.14.1' ./build.py --verbose make[2]: Entering directory '/home/zxuiji/Desktop/mitsy/gede-2.14.1/src' make[2]: Nothing to be done for 'first'. make[2]: Leaving directory '/home/zxuiji/Desktop/mitsy/gede-2.14.1/src' Compiling (please wait) make[1]: Leaving directory '/home/zxuiji/Desktop/mitsy/gede-2.14.1' readelf -all test.elf ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: None Version: 0x1 Entry point address: 0x407 Start of program headers: 64 (bytes into file) Start of section headers: 456 (bytes into file) Flags: 0x0 Size of this header: 0 (bytes) Size of program headers: 56 (bytes) Number of program headers: 7 Size of section headers: 64 (bytes) Number of section headers: 6 Section header string table index: 1 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] STRTAB 0000000000000348 00000348 0000000000000034 0000000000000001 A 0 0 1 [ 2] .interp NULL 000000000000037c 0000037c 0000000000000013 0000000000000001 A 0 0 1 [ 3] .symtab SYMTAB 000000000000038f 0000038f 0000000000000060 0000000000000018 A 1 4 8 [ 4] .text PROGBITS 00000000000003ef 000003ef 0000000000000011 0000000000000008 AX 0 0 8 [ 5] .text PROGBITS 0000000000000400 00000400 0000000000000011 0000000000000008 WAX 0 0 8 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align NULL 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0 PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x0000000000000188 0x0000000000000188 R 0x8 LOAD 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x0000000000000188 0x0000000000000188 R 0x8 LOAD 0x0000000000000348 0x0000000000000348 0x0000000000000348 0x0000000000000034 0x0000000000000034 R 0x1 INTERP 0x000000000000037c 0x000000000000037c 0x000000000000037c 0x0000000000000013 0x0000000000000013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x00000000000003ef 0x00000000000003ef 0x00000000000003ef 0x0000000000000011 0x0000000000000011 R E 0x1 LOAD 0x0000000000000400 0x0000000000000400 0x0000000000000400 0x0000000000000011 0x0000000000000011 RWE 0x1 Section to Segment mapping: Segment Sections... 00 01 02 03 04 .interp 05 .text 06 .text There is no dynamic section in this file. There are no relocations in this file. The decoding of unwind sections for machine type None is not currently supported. Symbol table '.symtab' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000400 0 FILE GLOBAL DEFAULT 1 test.c 2: 0000000000000400 7 FUNC GLOBAL DEFAULT 1 exit 3: 0000000000000407 10 FUNC GLOBAL DEFAULT 1 _start No version information found in this file. ./gede-2.14.1/src/gede --args ./test.elf 37.687| INFO | Using: /dev/pts/1 37.704| INFO | Found ctags ('ctags') 37.823| INFO | GDB | Log-stream | Function "_start" not defined. [1;33m37.823| WARN | Original-location in unknown format[1;0m Compilation finished successfully.