我只需要一个hello world演示来查看机器代码实际上是如何工作的.
虽然windows的EXE和linux'ELF接近机器代码,但它不是PURE
如何编写/执行PURE机器代码?
gel*_*sie 23
每个人都知道我们通常编写的应用程序是在操作系统上运行的.由它管理.
这意味着操作系统在机器上运行.所以我认为这就是你所说的PURE机器码.
因此,您需要研究操作系统的工作原理.
这是一些引导扇区的NASM汇编代码,可以在PURE中打印"Hello world".
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
Run Code Online (Sandbox Code Playgroud)
您可以在这里找到更多资源:http://wiki.osdev.org/Main_Page.
结束.
如果你已经安装了nasm并且有软盘,你可以
nasm boot.asm -f bin -o boot.bin
dd if=boot.bin of=/dev/fd0
Run Code Online (Sandbox Code Playgroud)
然后,您可以从此软盘启动,您将看到该消息.(注意:您应该首先启动计算机软盘.)
事实上,我建议你在完整的虚拟机中运行该代码,例如:bochs,virtualbox等.因为很难找到带软盘的机器.
因此,步骤是首先,您应该需要安装完整的虚拟机.其次,通过推荐创建一个可视软盘:bximage第三,将bin文件写入该可视软盘.最后,从该可视软盘启动您的可视机器.
注意:在https://wiki.osdev.org中,有一些关于该主题的基本信息.
Xlo*_*icX 23
您可以手动编写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
Run Code Online (Sandbox Code Playgroud)
WIN/MZ/PE:
shellcode2exe.py(采用asciihex shellcode并创建一个合法的MZ PE exe文件)脚本位置:
http://zeltser.com/reverse-malware/shellcode2exe.py.txt
依赖性:
提取
python setup.py build
sudo python setup.py install
Run Code Online (Sandbox Code Playgroud)
Gre*_*ill 15
听起来你正在寻找旧的16位DOS .COM文件格式..COM文件的字节在程序段中偏移100h处加载(将它们限制为最大大小为64k - 256字节),并且CPU仅在偏移100h处开始执行.没有标题或任何类型的任何必需信息,只是原始CPU指令.
D.S*_*nap 13
运行测试需要什么:Linux x86 或 x64(在我的情况下,我使用的是 Ubuntu x64)
开始吧
此程序集 (x86) 将值 666 移动到 eax 寄存器中:
movl $666, %eax
ret
Run Code Online (Sandbox Code Playgroud)
让我们对其进行二进制表示:
二进制的操作码movl(movl 是一个操作数大小为 32 的 mov)是 = 1011
二进制指令宽度= 1
二进制寄存器eax = 000
有符号的 32 位二进制数666 = 00000000 00000000 00000010 10011010
666转换为小端是 = 10011010 00000010 00000000 00000000
二进制指令ret(返回)是 = 11000011
所以最终我们的纯二进制指令将如下所示:
1011(movl)1(width)000(eax)10011010000000100000000000000000(666)
11000011(ret)
把它们放在一起:
1011100010011010000000100000000000000000
11000011
Run Code Online (Sandbox Code Playgroud)
为了执行它,二进制代码必须放在具有执行权限的内存页面中,我们可以使用以下 C 代码来做到这一点:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
/* Allocate size bytes of executable memory. */
unsigned char *alloc_exec_mem(size_t size)
{
void *ptr;
ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
exit(1);
}
return ptr;
}
/* Read up to buffer_size bytes, encoded as 1's and 0's, into buffer. */
void read_ones_and_zeros(unsigned char *buffer, size_t buffer_size)
{
unsigned char byte = 0;
int bit_index = 0;
int c;
while ((c = getchar()) != EOF) {
if (isspace(c)) {
continue;
} else if (c != '0' && c != '1') {
fprintf(stderr, "error: expected 1 or 0!\n");
exit(1);
}
byte = (byte << 1) | (c == '1');
bit_index++;
if (bit_index == 8) {
if (buffer_size == 0) {
fprintf(stderr, "error: buffer full!\n");
exit(1);
}
*buffer++ = byte;
--buffer_size;
byte = 0;
bit_index = 0;
}
}
if (bit_index != 0) {
fprintf(stderr, "error: left-over bits!\n");
exit(1);
}
}
int main()
{
typedef int (*func_ptr_t)(void);
func_ptr_t func;
unsigned char *mem;
int x;
mem = alloc_exec_mem(1024);
func = (func_ptr_t) mem;
read_ones_and_zeros(mem, 1024);
x = (*func)();
printf("function returned %d\n", x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
来源:https : //www.hanshq.net/files/ones-and-zeros_42.c
我们可以使用以下方法编译它:
gcc source.c -o binaryexec
要执行它:
./binaryexec
然后我们通过第一组指令:
1011100010011010000000100000000000000000
按回车
并传递返回指令:
11000011
按回车
最后 ctrl+d 结束程序并得到输出:
函数返回 666
操作系统没有运行指令,CPU会这样做(除非我们谈论虚拟机操作系统,确实存在,我正在考虑Forth或类似的事情).然而,操作系统确实需要一些元信息才能知道,文件确实包含可执行代码,以及它希望环境看起来如何.ELF不仅仅靠近机器代码.这是机器代码,以及操作系统的一些信息,知道它应该让CPU实际执行那个东西.
如果你想要比ELF更简单的东西,但是*nix,看看a.out格式,这要简单得多.传统上,如果没有指定输出名称,*nix C编译器会(仍)将其可执行文件写入名为a.out的文件中.
在 Windows(至少 32 位 Windows)上,您可以使用 .com 文件执行 RAW 指令。
例如,如果您将此字符串保存在记事本中,扩展名为 .com:
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
Run Code Online (Sandbox Code Playgroud)
它将打印一个字符串并启动您的防病毒软件。
| 归档时间: |
|
| 查看次数: |
55941 次 |
| 最近记录: |