如何在没有像EXE或ELF这样的容器的情况下手动编写和执行PURE机器代码?

我只需要一个hello world demo来看看机器代码是如何工作的。

虽然windows的EXE和linux的ELF是靠近机器码的,但它不是纯粹的

我如何编写/执行PURE机器码?

大家都知道,我们通常编写的应用程序是在操作系统上运行的。 并由其pipe理。

这意味着操作系统在机器上运行。 所以我认为你说的是​​PURE机器码。

所以,你需要研究操作系统是如何工作的。

这里是一些可以在PURE中打印“Hello world”的引导扇区的NASM汇编代码。

org xor ax, ax mov ds, ax mov si, msg boot_loop:lodsb or al, al jz go_flag mov ah, 0x0E int 0x10 jmp boot_loop go_flag: jmp go_flag msg db 'hello world', 13, 10, 0 times 510-($-$$) db 0 db 0x55 db 0xAA 

你可以在这里find更多的资源: http : //wiki.osdev.org/Main_Page 。

结束。

如果你已经安装了nasm并且有软盘,你可以

 nasm boot.asm -f bin -o boot.bin dd if=boot.bin of=/dev/fd0 

然后,您可以从这张软盘启动,您将看到该消息。 (注意:您应该首先启动计算机的软盘。)

实际上,我build议你在完整的虚拟机上运行这个代码,比如:bochs,virtualbox等。因为很难find一个带软盘的机器。

所以,步骤是首先,你需要安装一个完整的虚拟机。 其次,通过build立一个视觉软盘:bximage第三,把bin文件写到这个可视软盘上。 最后,从视觉软盘启动你的视觉机器。

注意:在https://wiki.osdev.org中; ,有一些关于该主题的基本信息。

这听起来像你正在寻找旧的16位DOS .COM文件格式 。 .COM文件的字节在程序段的偏移100h处加载(限制它们的最大大小为64k – 256字节),并且CPU简单地在偏移100h处开始执行。 没有任何标题或任何所需的信息,只是原始的CPU指令。

可以不使用汇编的情况下手动写入PURE机器代码

Linux / ELF: https : //github.com/XlogicX/m2elf 。 这还在进行中,我昨天才开始研究。

“Hello World”的源文件如下所示:

 b8 21 0a 00 00 #moving "!\n" into eax a3 0c 10 00 06 #moving eax into first memory location b8 6f 72 6c 64 #moving "orld" into eax a3 08 10 00 06 #moving eax into next memory location b8 6f 2c 20 57 #moving "o, W" into eax a3 04 10 00 06 #moving eax into next memory location b8 48 65 6c 6c #moving "Hell" into eax a3 00 10 00 06 #moving eax into next memory location b9 00 10 00 06 #moving pointer to start of memory location into ecx ba 10 00 00 00 #moving string size into edx bb 01 00 00 00 #moving "stdout" number to ebx b8 04 00 00 00 #moving "print out" syscall number to eax cd 80 #calling the linux kernel to execute our print to stdout b8 01 00 00 00 #moving "sys_exit" call number to eax cd 80 #executing it via linux sys_call 

WIN / MZ / PE:

shellcode2exe.py(需要asciihex shellcode并创build一个合法的MZ PE exe文件)脚本位置:

http://zeltser.com/reverse-malware/shellcode2exe.py.txt

依赖性:

corelabs.coresecurity.com/index.php?module=Wiki&action=attachment&type=tool&page=InlineEgg&file=InlineEgg-1.08.tar.gz

提取

python setup.py构build

sudo python setup.py安装

操作系统不运行的指示,CPU(除非我们正在谈论虚拟机操作系统,这是存在的,我正在考虑Forth或类似的东西)。 然而操作系统确实需要一些元信息来知道,一个文件实际上包含可执行代码,以及它期望它的环境如何。 ELF不只是机器码附近 。 这机器代码,连同操作系统的一些信息,以知道它应该把CPU实际执行的东西。

如果你想要比ELF更简单的东西,但* nix,请看看a.out格式,这是非常简单的。 传统上,如果没有指定输出名称,nix C编译器(仍)将其可执行文件写入名为a.out的文件。

在Windows上 – 至less32位Windows – 您可以使用.com文件执行RAW指令。

例如,如果你把这个string保存在带有.com扩展名的记事本中:

 X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* 

它会打印一个string,并引发您的防病毒软件。

在定位embedded式系统时,您可以制作严格来自程序的指令和相关数据的ROM或RAM的二进制映像。 通常可以将该二进制文件写入闪存/ ROM并运行。

操作系统想要知道更多的东西,开发人员经常希望在文件中留下更多的内容,以便以后可以debugging或做其他事情(用一些可识别的符号名称进行反汇编)。 另外,embedded或在操作系统上,您可能需要将.text与.bata从.rodata等文件格式分离,并提供一个文件格式,例如.elf提供了一个机制,首选的用例是用一些无论是操作系统还是对微控制器的ROM和RAM进行编程,

.exe也有一些标题信息。 正如所提到的COM没有加载在地址0x100h并在那里分支。

从一个可执行文件创build一个原始的二进制文件,例如你可以做一个像gcc创build的精灵文件

objcopy file.elf -O二进制文件.bin

如果程序是分段的(.text,.data等),而这些段不是背靠背的,二进制可能会变得很大。 再次使用embedded作为一个例子,如果rom是在0x00000000和数据或bss是在0x20000000,即使您的程序只有4个字节的数据objcopy将创build一个0x20000004字节文件填充.text和.data之间的差距(因为它应该因为那是你要求的)。

你在做什么? 读取elf或intel hex或srec文件是相当简单的,从中可以看到二进制文件的所有位和字节。 或者分解精灵或者其他东西,也会以一种人类可读的forms向你显示。 (objdump -D file.elf> file.list)

使用纯机器码,您可以使用任何能够编写文件的语言。 即使visual basic.net也可以在写入时在inttypes之间交换时写8,16,32,64位。

你甚至可以设置为vb根据setpixel所需要的循环写出机器代码,其中x,y改变,并且你有你的argb颜色。

或者,在Windows中定期创build您的vb.net程序,并使用NGEN.exe生成程序的本机代码文件。 它创build了纯粹的专用于ia-32的机器代码,一次性抛出JITdebugging器。

这是很好的反应,但为什么有人想这样做可能会更好地指导答案。 我认为最重要的原因是要完全控制他们的机器,尤其是高速caching写入,以获得最佳性能,并防止任何操作系统共享处理器或虚拟化代码(从而减慢速度),尤其是在这些日子里窥探你的代码也是如此。 据我所知,汇编不处理这些问题,M $ / Intel和其他公司将此视为侵权行为或“黑客”。 然而,这是非常错误的。 如果你的汇编代码被交给了操作系统或专有硬件,真正的优化(潜在的GHz频率)将是遥不可及的。 这对于科学技术来说是一个非常重要的问题,因为我们的计算机如果不经过硬件优化就不能充分发挥其应用的潜力,而且往往要比它低几个数量级。 有可能是一些解决方法或一些开源硬件,使这个,但我还没有find它。 便士为任何人的想法。

我不是一个程序员,所有我所知道的编程知识都是在我完成了Kahn Academy的JavaScript部分时学到的,但是我甚至不记得什么是for循环。 我search了一些关于机器代码的东西,并find了编程16位Windows机器代码的指南,它的第一个程序是生成一个Hello, World!

代码是:

 ba 0c 01 b4 09 cd 21 b8 00 4c cd 21 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 0d 0a 24 

在二进制中,这转换为:

 10111010 00001100 00000001 10110100 00001001 11001101 00100001 10111000 00000000 01001100 11001101 00100001 01001000 01100101 01101100 01101100 01101111 00101100 00100000 01010111 01101111 01110010 01101100 01100100 00100001 00100001 00001010 00100100 

我有一堆无论你叫什么,它分开的代码行,但由于某种原因,它不显示为我。 也许它会为你。

Interesting Posts