【发布时间】:2013-08-30 19:46:58
【问题描述】:
按照this 的指令,我只生成了大小为 a.out 的 528 字节(当 gcc main.c 最初给了我 8539 字节的大文件时)。
main.c 是:
int main(int argc, char** argv) {
return 42;
}
但我已经从这个程序集文件构建了 a.out:
main.s:
; tiny.asm
BITS 64
GLOBAL _start
SECTION .text
_start:
mov eax, 1
mov ebx, 42
int 0x80
与:
me@comp# nasm -f elf64 tiny.s
me@comp# gcc -Wall -s -nostartfiles -nostdlib tiny.o
me@comp# ./a.out ; echo $?
42
me@comp# wc -c a.out
528 a.out
因为我需要机器码:
objdump -d a.out
a.out: file format elf64-x86-64
Disassembly of section .text:
00000000004000e0 <.text>:
4000e0: b8 01 00 00 00 mov $0x1,%eax
4000e5: bb 2a 00 00 00 mov $0x2a,%ebx
4000ea: cd 80 int $0x80
># objdump -hrt a.out
a.out: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 00000000004000b0 00000000004000b0 000000b0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000000c 00000000004000e0 00000000004000e0 000000e0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
no symbols
文件采用 little endian 约定:
me@comp# readelf -a a.out
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: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x4000e0
Start of program headers: 64 (bytes into file)
Start of section headers: 272 (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: 3
现在我想这样执行:
#include <unistd.h>
// which version is (more) correct?
// this might be related to endiannes (???)
char code[] = "\x01\xb8\x00\x00\xbb\x00\x00\x2a\x00\x00\x80\xcd\x00";
char code_v1[] = "\xb8\x01\x00\x00\x00\xbb\x2a\x00\x00\x00\xcd\x80\x00";
int main(int argc, char **argv)
{
/*creating a function pointer*/
int (*func)();
func = (int (*)()) code;
(int)(*func)();
return 0;
}
但是我得到分段错误。 我的问题是:这是一段文字
4000e0: b8 01 00 00 00 mov $0x1,%eax
4000e5: bb 2a 00 00 00 mov $0x2a,%ebx
4000ea: cd 80 int $0x80
(这个机器代码)我真正需要的一切?我做错了什么(字节序??),也许我只需要从 SIGSEGV 开始以不同的方式调用它?
【问题讨论】:
-
您不能只将几个随机字节视为一个函数。您必须尊重编译器的调用约定,并提供合适的函数序言和结语。
-
当然,这个操作码是用相同的编译器生成的,不是随机的,所以应该没问题,你知道我该怎么做吗?为什么我可以从终端运行它?
-
首先,您需要确保代码驻留在可执行内存中。尝试添加类似
__attribute__((section, ".text"))或类似的内容(参见手册)。正如我所说,确保实现正确的调用约定。 -
谢谢,我将尝试从 gcc 正常方式生成的 a.out 中获取操作码,但将操作码然后放入 asm 并像以前一样构建 a.out 以避免运行时库开销。你认为这是个好主意吗?不,我将只使用来自 a.out 的操作码,因为我在这里不使用任何库
-
我有这个:* 00000000004004b4
55 push %rbp 00000000004004b5 48 89 e5 mov %rsp,%rbp 00000000004004b8 89 7d fc mov %ed 0x4(%rbp) 00000000004004bb 48 89 75 f0 mov %rsi,-0x10(%rbp) /NetBeansProjects/examples/tiny_c/tiny.c:15 返回 42; 00000000004004bf b8 2a 00 00 00 mov $0x2a,%eax /NetBeansProjects/examples/tiny_c/tiny.c:16 } 00000000004004c4 c9 leaveq 000000000040034c5
标签: c gcc assembly nasm opcode