section .text
global _start
_start:
xor eax, eax
push eax ; 0 to finish the /bin//sh string
push 0x68732f2f ; //sh
push 0x6e69622f ; /bin
mov ebx, esp
mov al, 0xb
int 0x80
如果我这样做的话,可以正常工作:
$ nasm -f elf shellcode.asm && ld -o shellcode shellcode.o
$ ./shellcode
$ # the new shell
但是现在,带有十六进制翻译:
$ objdump -s shellcode
shellcode: file format elf32-i386
Contents of section .text:
8048060 31c05068 2f2f7368 682f6269 6e89e3b0 1.Ph//shh/bin...
8048070 0bcd80 ...
在这里使用:
const char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80";
int main(){
(*(void(*)()) shellcode)();
return 0;
}
结果是:
$ gcc -o shellcode shellcode.c
$ ./shellcode
Segmentation fault
我尝试练习ASM并重新创建此处提供的ASM。我无法解释的区别是,在他的有效负载上,他将一个额外的
0
和/bin//sh
字符串的地址推入了堆栈。我虽然那是因为我正在使用fastcall约定,我不必设置堆栈,但是显然这里还有更多操作。 />
编辑:
当我尝试从
gdb
运行程序时,我得到以下结果:$ gdb ./shellcode
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
0x080484b3 in shellcode ()
这是
readelf
命令的输出:$ readelf -l -S shellcode
There are 30 section headers, starting at offset 0x1150:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481cc 0001cc 000040 10 A 6 1 4
[ 6] .dynstr STRTAB 0804820c 00020c 000045 00 A 0 0 1
[ 7] .gnu.version VERSYM 08048252 000252 000008 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 0804825c 00025c 000020 00 A 6 1 4
[ 9] .rel.dyn REL 0804827c 00027c 000008 08 A 5 0 4
[10] .rel.plt REL 08048284 000284 000010 08 A 5 12 4
[11] .init PROGBITS 08048294 000294 000023 00 AX 0 0 4
[12] .plt PROGBITS 080482c0 0002c0 000030 04 AX 0 0 16
[13] .text PROGBITS 080482f0 0002f0 000192 00 AX 0 0 16
[14] .fini PROGBITS 08048484 000484 000014 00 AX 0 0 4
[15] .rodata PROGBITS 08048498 000498 00001c 00 A 0 0 4
[16] .eh_frame_hdr PROGBITS 080484b4 0004b4 00002c 00 A 0 0 4
[17] .eh_frame PROGBITS 080484e0 0004e0 0000b0 00 A 0 0 4
[18] .init_array INIT_ARRAY 08049f08 000f08 000004 00 WA 0 0 4
[19] .fini_array FINI_ARRAY 08049f0c 000f0c 000004 00 WA 0 0 4
[20] .jcr PROGBITS 08049f10 000f10 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08049f14 000f14 0000e8 08 WA 6 0 4
[22] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 0804a000 001000 000014 04 WA 0 0 4
[24] .data PROGBITS 0804a014 001014 000008 00 WA 0 0 4
[25] .bss NOBITS 0804a01c 00101c 000004 00 WA 0 0 1
[26] .comment PROGBITS 00000000 00101c 00002b 01 MS 0 0 1
[27] .shstrtab STRTAB 00000000 001047 000106 00 0 0 1
[28] .symtab SYMTAB 00000000 001600 000430 10 29 45 4
[29] .strtab STRTAB 00000000 001a30 00024e 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Elf file type is EXEC (Executable file)
Entry point 0x80482f0
There are 9 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00590 0x00590 R E 0x1000
LOAD 0x000f08 0x08049f08 0x08049f08 0x00114 0x00118 RW 0x1000
DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x0004b4 0x080484b4 0x080484b4 0x0002c 0x0002c R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
与该shellcode的比较: br />
Hamza (working) | me
ASM
xor eax, eax | xor eax, eax
push eax | push eax
push 0x68732f2f | push 0x68732f2f
push 0x6e69622f | push 0x6e69622f
mov ebx, esp | mov ebx, esp
push eax |
push ebx |
mov esp, ecx |
mov al, 0xb | mov al, 0xb
int 0x80 | int 0x80
Stack before the interrupt (each line is a word)
&(/bin//sh) | /bin
0 | //sh
/bin | 0
//sh |
0 |
Registers before the interrupt
eax 0xb | 0xb
ebx &(/bin//sh) | &(/bin//sh)
ecx esp | ?
如您所见,堆栈通过更改字符串的地址和一个额外的
0
来改变,并将其ecx
寄存器设置为最后一个esp
值。这些差异使他的shellcode可以正常工作(直接在nasm
和ld
以及C
程序内部使用,没有任何更改)。编辑:
有些进步,当有效载荷在C程序中运行时,还有一条额外的指令:中断,请使用
ecx
清除寄存器可解决此问题。这是工作中的asm:
#1 楼
shellcode的问题以及为什么不从C程序运行而为何与众不同的原因是初始值。 br />eax
= 0x0b ebx
= ptr到文件名ecx
= ptr到argv edx
= ptr到环境变量,但是实际上重要的只有
ebx
和eax
,另外两个我们可以将其无效。是0x0
,因此我们免费获得ecx
和edx
的无效。从C程序执行shellcode并非如此。
如您所见,寄存器已经具有一些初始值,因此需要正确准备它们。这就是为什么添加
xor ecx,ecx
可以解决此问题的原因。 对于您从
ecx
取得的示例已分配给堆栈指针,但是在堆栈上有一个指向“ / bin / sh”的值也可以(并且甚至可能比0x00
更好) #2 楼
好的,因此根据gdb
,shellcode确实可以运行,因此可能已将其放入.text
中。您应该尝试逐步浏览Shellcode(例如使用stepi
)以查看错误的指令。评论
好的,我做到了,并且有效负载上还有一条额外的说明,我将发布更新。
– nobe4
17年9月2日在21:03
评论
可能您的字符串bin,sh没有空终止符,而push 0满足了它确实如此,这就是为什么我第一次推eax ...
您的数据部分可执行吗?发布readelf -l -S的输出。当您在其中运行已编译的程序时,gdb会怎么说?
嘿@IgorSkochinsky:看我的编辑。看来我的.data是可写和可分配的,但不能执行。可以吗?同样,当我尝试从asm生成的可执行文件中读取elf时,只有可执行的.text标头。
所以根据gdb它确实可以运行。 “将堆栈设置更改为”正确”意味着什么?”