为什么我不能通过系统调用退出 shellcode?
Why can't i exit from shellcode with a syscall?
我尝试制作一个程序,您可以在其中放入一些十六进制的组装程序集,然后 运行 它。
使用像 int3
这样的简单指令它可以工作,但是当我尝试使用系统调用退出程序时它不起作用。
我用 rasm2
组装了它
mov eax, 1
mov ebx, 12
int 0x80
然后把它作为参数./Programm b801000000bb0c000000cd80 1
但是我遇到了段错误。
这是我的代码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
char *base16dec(char *b16str) {
size_t stingrlength = strlen(b16str);
char *decodedstr = malloc(stingrlength / 2);
for (size_t i = 0; i < stingrlength; i += 2) {
u_int8_t num = 0;
char stringIn[3];
stringIn[0] = b16str[i];
stringIn[1] = b16str[i+1];
stringIn[2] = 0;
sscanf(stringIn, "%hhx", &num);
decodedstr[i/2] = (char) num;
}
return decodedstr;
}
这将解码十六进制字符串
int main(int argc, char *argv[]) {
char *dirstr = "XXXXXX";
char dir[7];
strcpy(dir, dirstr);
int fd = mkstemp(dir);
if (fd == -1) {
dirstr = "/tmp/XXXXXX";
char dir[12];
strcpy(dir, dirstr);
fd = mkstemp(dir);
}
unlink(dir);
这将创建存储程序集的 tmp 文件
char *stringIn;
if (argc == 2) {
stringIn = malloc(strlen(argv[1]));
strcpy(stringIn, argv[1]);
} else if (argc == 3) {
u_int8_t num = 0;
sscanf(argv[2], "%hhu", &num);
if (num == 1) {
char *done = base16dec(argv[1]);
stringIn = malloc(strlen(done));
strcpy(stringIn, done);
} else {
stringIn = malloc(strlen(argv[1]));
strcpy(stringIn, argv[1]);
}
} else {
stringIn = malloc(1024);
scanf("%s", stringIn);
char *done = base16dec(stringIn);
stringIn = malloc(strlen(done));
strcpy(stringIn, done);
}
这会解析输入并将其复制到 stringIn
ftruncate(fd, strlen(stringIn));
u_int8_t *code = mmap(NULL, strlen(stringIn), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE , fd, 0);
这会扩展 tmp 文件并使其可执行并创建一个指向它的指针,名为 code
for (int i = 0; i < 1024; i++) {
code[i] = (u_int8_t) stringIn[i];
}
这会将汇编字节复制到 code
#if __x86_64__
__asm__(
"mov %0, %%rbx\n"
"jmp *%%rbx"
:
: "g" (code)
: "memory"
);
#elif __i386__
__asm__(
"mov %0, %%ebx\n"
"jmp *%%ebx"
:
: "r" (code)
);
#else
#endif
这会跳转到程序集
return 0;
}
编辑:
我无法使用 gdb 调试 shellcode
我使用 64 位 Linux Mint
我尝试使用 strcpy
复制 0
因为这是一个 shellcode,所以不能有空字节。在您的代码中,您有 2 个带立即数的 movs 被填充为 32 位
mov eax, 1
mov ebx, 12
编码为 B801000000BB0C000000,当 C 遇到空字节时它认为字符串已经结束所以它只会结束复制部分指令然后执行垃圾。
相反,您需要使用:
xor eax, eax
inc eax
xor ebx, ebx
mov bl, 12
这将为您的系统调用提供您想要的值,并且不会编码为任何空字节。
我尝试制作一个程序,您可以在其中放入一些十六进制的组装程序集,然后 运行 它。
使用像 int3
这样的简单指令它可以工作,但是当我尝试使用系统调用退出程序时它不起作用。
我用 rasm2
mov eax, 1
mov ebx, 12
int 0x80
然后把它作为参数./Programm b801000000bb0c000000cd80 1
但是我遇到了段错误。
这是我的代码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
char *base16dec(char *b16str) {
size_t stingrlength = strlen(b16str);
char *decodedstr = malloc(stingrlength / 2);
for (size_t i = 0; i < stingrlength; i += 2) {
u_int8_t num = 0;
char stringIn[3];
stringIn[0] = b16str[i];
stringIn[1] = b16str[i+1];
stringIn[2] = 0;
sscanf(stringIn, "%hhx", &num);
decodedstr[i/2] = (char) num;
}
return decodedstr;
}
这将解码十六进制字符串
int main(int argc, char *argv[]) {
char *dirstr = "XXXXXX";
char dir[7];
strcpy(dir, dirstr);
int fd = mkstemp(dir);
if (fd == -1) {
dirstr = "/tmp/XXXXXX";
char dir[12];
strcpy(dir, dirstr);
fd = mkstemp(dir);
}
unlink(dir);
这将创建存储程序集的 tmp 文件
char *stringIn;
if (argc == 2) {
stringIn = malloc(strlen(argv[1]));
strcpy(stringIn, argv[1]);
} else if (argc == 3) {
u_int8_t num = 0;
sscanf(argv[2], "%hhu", &num);
if (num == 1) {
char *done = base16dec(argv[1]);
stringIn = malloc(strlen(done));
strcpy(stringIn, done);
} else {
stringIn = malloc(strlen(argv[1]));
strcpy(stringIn, argv[1]);
}
} else {
stringIn = malloc(1024);
scanf("%s", stringIn);
char *done = base16dec(stringIn);
stringIn = malloc(strlen(done));
strcpy(stringIn, done);
}
这会解析输入并将其复制到 stringIn
ftruncate(fd, strlen(stringIn));
u_int8_t *code = mmap(NULL, strlen(stringIn), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE , fd, 0);
这会扩展 tmp 文件并使其可执行并创建一个指向它的指针,名为 code
for (int i = 0; i < 1024; i++) {
code[i] = (u_int8_t) stringIn[i];
}
这会将汇编字节复制到 code
#if __x86_64__
__asm__(
"mov %0, %%rbx\n"
"jmp *%%rbx"
:
: "g" (code)
: "memory"
);
#elif __i386__
__asm__(
"mov %0, %%ebx\n"
"jmp *%%ebx"
:
: "r" (code)
);
#else
#endif
这会跳转到程序集
return 0;
}
编辑:
我无法使用 gdb 调试 shellcode
我使用 64 位 Linux Mint
我尝试使用 strcpy
0
因为这是一个 shellcode,所以不能有空字节。在您的代码中,您有 2 个带立即数的 movs 被填充为 32 位
mov eax, 1
mov ebx, 12
编码为 B801000000BB0C000000,当 C 遇到空字节时它认为字符串已经结束所以它只会结束复制部分指令然后执行垃圾。
相反,您需要使用:
xor eax, eax
inc eax
xor ebx, ebx
mov bl, 12
这将为您的系统调用提供您想要的值,并且不会编码为任何空字节。