Live data from Hacker News

Manually Creating an ELF Executable

robinhoksbergen.com

21–27 of 27 posts

Re: Manually Creating an ELF Executable

#21
post #17
post #14

Earlier quoted context omitted.

It's the HWLENADDR you're talking about? It's placed as the last byte in (not in: after) the string. Down in the final product the edx part ends up BA B1 80 04 08 (0x080480B1). It's a pointer to that '14' stored 13 bytes past the start of the string ("hello, world\n" is 13 bytes). The ecx points to (0x..A4), exactly 13 less than B1. edit: You're probably thinking it should be placed as an immediate value. It's hard t…

I see where I was off by one byte (14 instead of 13) but that still doesn't explain things. The code doesn't load edx with 13 but instead loads it with 0x080480B1. If you wanted to fetch a byte from that address and load it into edx you'd need to use something like "movzx edx, byte ptr [0x080480B1]" but the code on the page just does "mov edx, 0x080480B1". In fact when you run this the code actually prints out not ju…

I agree. This is definitely a bug. The correct instruction is 8b 15 B1800408 or a MOV EDX, [0x080480B1]. I hope I got my register number correct on that.

The movzx/movsx is only needed when you're doing something like movzx EAX, BX. That way you're sure the CPU does what you expect when moving from a smaller register to a larger one. Man do I hate x86.

Re: Manually Creating an ELF Executable

#22
post #2

Awesome. My wife and kids asked me if you can write computer programs using just 1s and 0s and I told them that assembly was the lowest you could use, apparently mistakenly. Gonna have to try this out!

Here's the DOS COM version. Copy this into HELLO.COM with a hex editor of your choice. It will run in dosbox (that's what I tested on) and should run in Windows COMMAND.COM on a 32-bit system. b409ba0d01cd21b44cb05dcd2148454c4c4f20574f524c442124 Here's the breakdown: b409 MOV AH, 09h ; OUTPUT string ba0d01 MOV DX, 010Dh ; address of output buffer (remember we're loaded into 0100h) cd21 INT 21h b44c MOV AH, 4Ch ; TERM…

You can cheat a little bit and use RET rather than INT 21h to save a few bytes.

The way this works is pretty clever - the COM loader places an INT 20h instruction (the old-style terminate function) at offset 0 in the PSP (the 100h-byte-long structure loaded right before the contents of the COM file). The loader also sets up the word above the initial stack pointer to 0 so that a RET will return to address 0 and execute the INT 20h.

Re: Manually Creating an ELF Executable

#23
post #22

Earlier quoted context omitted.

Here's the DOS COM version. Copy this into HELLO.COM with a hex editor of your choice. It will run in dosbox (that's what I tested on) and should run in Windows COMMAND.COM on a 32-bit system. b409ba0d01cd21b44cb05dcd2148454c4c4f20574f524c442124 Here's the breakdown: b409 MOV AH, 09h ; OUTPUT string ba0d01 MOV DX, 010Dh ; address of output buffer (remember we're loaded into 0100h) cd21 INT 21h b44c MOV AH, 4Ch ; TERM…

You can cheat a little bit and use RET rather than INT 21h to save a few bytes. The way this works is pretty clever - the COM loader places an INT 20h instruction (the old-style terminate function) at offset 0 in the PSP (the 100h-byte-long structure loaded right before the contents of the COM file). The loader also sets up the word above the initial stack pointer to 0 so that a RET will return to address 0 and execu…

And the RET saves you one byte over the INT 20h. Oh what a different world we live in now.

Re: Manually Creating an ELF Executable

#24
post #13

Is it explained where the values for ecx and edx get filled in? I'm confused as to why edx=0x080480B1 instead of the length of the string (14).

Author here. And yes, that's a bug. I recently restored most of the pages on my website, and didn't check whether each page was the most recent version. When I first wrote the HOWTO, I for some reason was under the impression that the 'write' system call required the address of the length of the string to be loaded in EDX, which is obviously a bit silly. You're right that EDX should just hold the value 13. I'll change this as soon as I get the time.

Re: Manually Creating an ELF Executable

#25
post #2

Awesome. My wife and kids asked me if you can write computer programs using just 1s and 0s and I told them that assembly was the lowest you could use, apparently mistakenly. Gonna have to try this out!

Even more impressive than this hello world and with 29 byte just 3 byte bigger:

  b013cd10c52f0f3197b18cb38cfe018009804b75f881c74001e2f0ebe9
I made this in 2001 and used it once in a job interview, I asked for access to a computer running XP, opened cmd.exe and debug.exe, entered the asm code (rdtsc is not supported by debug.exe but i remembered the 0f31 opcode) and blew someones mind.

Re: Manually Creating an ELF Executable

#27
post #17
post #14

Earlier quoted context omitted.

It's the HWLENADDR you're talking about? It's placed as the last byte in (not in: after) the string. Down in the final product the edx part ends up BA B1 80 04 08 (0x080480B1). It's a pointer to that '14' stored 13 bytes past the start of the string ("hello, world\n" is 13 bytes). The ecx points to (0x..A4), exactly 13 less than B1. edit: You're probably thinking it should be placed as an immediate value. It's hard t…

I see where I was off by one byte (14 instead of 13) but that still doesn't explain things. The code doesn't load edx with 13 but instead loads it with 0x080480B1. If you wanted to fetch a byte from that address and load it into edx you'd need to use something like "movzx edx, byte ptr [0x080480B1]" but the code on the page just does "mov edx, 0x080480B1". In fact when you run this the code actually prints out not ju…

Yeah, you're right. The syscall does ask for a size_t. It now looks correct. The whole length-after-the-string part is edited out, and the value is indeed placed as immediate (as the syscall wants). Now the binary ends with "hello, world\n" and 14 is inserted directly (b9 a4 80 04 08, ba 0d 00 00 00).
Post reply on HN