Символ печати кода оболочки (64 бита)
У меня проблема с этим шелл-кодом. Когда я запускаю код ассемблера, он печатает символ, но когда я вызываю его как функцию из c, это не так. Я использовал gdb для проверки всех выполненных инструкций, и он, кажется, выполняет все инструкции. Это очень странно, потому что я отлаживал обе версии asm и c, и они делают то же самое, но в int 0x80 он ничего не печатает для кода C. Это код C:
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
int (*sc)();
/****************************************************************
0000000000000000 <main>: /
0: 48 31 c9 xor %rcx,%rcx /
3: 48 31 c0 xor %rax,%rax /
6: eb 13 jmp 1b <n> /
/
0000000000000008 <et>: /
8: 59 pop %rcx /
9: 48 31 c0 xor %rax,%rax /
c: 48 31 db xor %rbx,%rbx /
f: 48 31 d2 xor %rdx,%rdx /
12: b0 04 mov $0x4,%al /
14: b3 01 mov $0x1,%bl /
16: b2 01 mov $0x1,%dl /
18: cd 80 int $0x80 /
1a: c3 retq /
/
000000000000001b <n>: /
1b: e8 e8 ff ff ff callq 8 <et> /
/
0000000000000020 <abc>: /
20: 77 .byte 0x77 /
... /
******************************************************************/
char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw";
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw";
int main(int argc, char **argv) {
char *ptr = mmap(0, sizeof(shellcode),
PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON
| MAP_PRIVATE, -1, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
exit(-1);
}
memcpy(ptr, shellcode, sizeof(shellcode));
sc = ptr;
(void)((void(*)())ptr)();
printf("\n");
return 0;
}
Это код носа:
global main
main: ; main
xor rcx, rcx ; eficient way turning register to 0
xor rax, rax ; exclusive or
jmp n
et:
pop rcx
xor rax, rax
xor rbx, rbx
xor rdx, rdx
mov al, 4 ; Number of system call (write)
mov bl, 1 ; argument(1=stdout)
mov dl, 1 ; number of characters
int 0x80
ret
n:
call et
abc: db 'w'
РЕДАКТИРОВАТЬ: я решил проблему. На этой веб-странице: http://www.exploit-db.com/papers/13065/ Я обнаружил, что в 64 битах системные вызовы должны вызываться с использованием системного вызова int 0x80, а регистры аргументов различаются. Затем я нашел эту другую веб-страницу: http://cs.lmu.edu/~ray/notes/linuxsyscalls/. У него есть несколько примеров выполнения этих системных вызовов, думаю, что это хорошая веб-страница.
Но теперь возникает вопрос: почему это работает с кодом Nasm? Это что-то о совместимости? Может быть, код на ассемблере выполнялся в режиме совместимости, потому что ассемблер обнаружил инструкцию int 0x80, а в C компилятор не смог, потому что он не может интерпретировать шелл-код?
Я оставляю здесь рабочий код C:
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
int (*sc)();
/****************************************************************
0000000000000000 <main>: /
0: 48 31 c9 xor %rcx,%rcx /
3: 48 31 c0 xor %rax,%rax /
6: eb 16 jmp 1e <n> /
/
0000000000000008 <et>: /
8: 5e pop %rsi /
9: 48 31 c0 xor %rax,%rax /
c: 48 31 db xor %rbx,%rbx /
f: 48 31 d2 xor %rdx,%rdx /
12: b0 01 mov $0x1,%al /
14: b3 01 mov $0x1,%bl /
16: 48 89 df mov %rbx,%rdi /
19: b2 01 mov $0x1,%dl /
1b: 0f 05 syscall /
1d: c3 retq /
/
000000000000001e <n>: /
1e: e8 e5 ff ff ff callq 8 <et> /
/
0000000000000023 <abc>: /
23: 77 .byte 0x77 /
/
****************************************************************/
char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x16\x5e\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x01\xb3\x01\x48\x89\xdf\xb2\x01\x0f\x05\xc3\xe8\xe5\xff\xff\xffw";
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw";
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw";
int main(int argc, char **argv) {
char *ptr = mmap(0, sizeof(shellcode),
PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON
| MAP_PRIVATE, -1, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
exit(-1);
}
memcpy(ptr, shellcode, sizeof(shellcode));
sc = ptr;
(void)((void(*)())ptr)();
printf("\n");
return 0;
}
1 ответ
Вы, вероятно, создавали файл ELF как 32-битный. Даже если ваша ОС 64-разрядная, а двоичная 32-разрядная, она работает в режиме совместимости.
То же самое происходит в Windows (это называется "Windows-on-Windows-64" или "WOW64").