我有以下工作的NASM代码:
global _start section .text _start: mov eax, 0x4 mov ebx, 0x1 mov ecx, message mov edx, 0xF int 0x80 mov eax, 0x1 mov ebx, 0x0 int 0x80 section .data message: db "Hello, World!", 0dh, 0ah
在屏幕上显示“ Hello,World!\ n”。我还具有以下C包装器,其中包含先前的NASM对象代码:
char code[] = "\xb8\x04\x00\x00\x00" "\xbb\x01\x00\x00\x00" "\xb9\x00\x00\x00\x00" "\xba\x0f\x00\x00\x00" "\xcd\x80\xb8\x01\x00" "\x00\x00\xbb\x00\x00" "\x00\x00\xcd\x80"; int main(void) { (*(void(*)())code)(); }
但是,当我运行代码时,似乎未执行汇编代码,但程序退出正常。有任何想法吗?
谢谢
注入此shellcode时,您不知道位置message:
message
mov ecx, message
在注入的过程中,它可以是任何东西,但不会如此,"Hello world!\r\n"因为仅转储文本部分时它位于数据部分。您可以看到您的shellcode没有"Hello world!\r\n":
"Hello world!\r\n"
"\xb8\x04\x00\x00\x00" "\xbb\x01\x00\x00\x00" "\xb9\x00\x00\x00\x00" "\xba\x0f\x00\x00\x00" "\xcd\x80\xb8\x01\x00" "\x00\x00\xbb\x00\x00" "\x00\x00\xcd\x80";
这是Shellcode开发中的常见问题,解决方法是这样的:
global _start section .text _start: jmp MESSAGE ; 1) lets jump to MESSAGE GOBACK: mov eax, 0x4 mov ebx, 0x1 pop ecx ; 3) we are poping into `ecx`, now we have the ; address of "Hello, World!\r\n" mov edx, 0xF int 0x80 mov eax, 0x1 mov ebx, 0x0 int 0x80 MESSAGE: call GOBACK ; 2) we are going back, since we used `call`, that means ; the return address, which is in this case the address ; of "Hello, World!\r\n", is pushed into the stack. db "Hello, World!", 0dh, 0ah section .data
现在转储文本部分:
$ nasm -f elf shellcode.asm $ ld shellcode.o -o shellcode $ ./shellcode Hello, World! $ objdump -d shellcode shellcode: file format elf32-i386 Disassembly of section .text: 08048060 <_start>: 8048060: e9 1e 00 00 00 jmp 8048083 <MESSAGE> 08048065 <GOBACK>: 8048065: b8 04 00 00 00 mov $0x4,%eax 804806a: bb 01 00 00 00 mov $0x1,%ebx 804806f: 59 pop %ecx 8048070: ba 0f 00 00 00 mov $0xf,%edx 8048075: cd 80 int $0x80 8048077: b8 01 00 00 00 mov $0x1,%eax 804807c: bb 00 00 00 00 mov $0x0,%ebx 8048081: cd 80 int $0x80 08048083 <MESSAGE>: 8048083: e8 dd ff ff ff call 8048065 <GOBACK> 8048088: 48 dec %eax <-+ 8048089: 65 gs | 804808a: 6c insb (%dx),%es:(%edi) | 804808b: 6c insb (%dx),%es:(%edi) | 804808c: 6f outsl %ds:(%esi),(%dx) | 804808d: 2c 20 sub $0x20,%al | 804808f: 57 push %edi | 8048090: 6f outsl %ds:(%esi),(%dx) | 8048091: 72 6c jb 80480ff <MESSAGE+0x7c> | 8048093: 64 fs | 8048094: 21 .byte 0x21 | 8048095: 0d .byte 0xd | 8048096: 0a .byte 0xa <-+ $
我标记的行是我们的"Hello, World!\r\n"字符串:
"Hello, World!\r\n"
$ printf "\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a" Hello, World! $
因此,我们的C包装器将是:
char code[] = "\xe9\x1e\x00\x00\x00" // jmp 8048083 <MESSAGE> "\xb8\x04\x00\x00\x00" // mov $0x4,%eax "\xbb\x01\x00\x00\x00" // mov $0x1,%ebx "\x59" // pop %ecx "\xba\x0f\x00\x00\x00" // mov $0xf,%edx "\xcd\x80" // int $0x80 "\xb8\x01\x00\x00\x00" // mov $0x1,%eax "\xbb\x00\x00\x00\x00" // mov $0x0,%ebx "\xcd\x80" // int $0x80 "\xe8\xdd\xff\xff\xff" // call 8048065 <GOBACK> "Hello wolrd!\r\n"; // OR "\x48\x65\x6c\x6c\x6f\x2c\x20\x57" // "\x6f\x72\x6c\x64\x21\x0d\x0a" int main(int argc, char **argv) { (*(void(*)())code)(); return 0; }
让我们测试一下:
$ gcc test.c -o test $ ./test Hello wolrd! $
有用。