计算 C 中两个标签之间的代码大小(操作码字节数)
Calculate code size (number of opcode bytes) between two labels in C
基于这个 MSVC Windows 反汇编,有没有一种方法可以确定标签之间的字节数
jmp_code_start 和 jmp_code_finish?手动计算操作码字节 B8 D0 10 36 00 2D C3 00 00 00 89 45 FC FF 55 FC 显示有 16 个字节,但这很乏味。也许有更好的技术?
int main(int argc, char* argv[])
{
003610D0 66 90 xchg ax,ax
003610D2 55 push ebp
003610D3 8B EC mov ebp,esp
003610D5 51 push ecx
jmp_code_start:;
char (*jmp)() = (char*)&main - sizeof(shellcode);
003610D6 B8 D0 10 36 00 mov eax,offset main (03610D0h)
003610DB 2D C3 00 00 00 sub eax,0C3h
003610E0 89 45 FC mov dword ptr [jmp],eax
jmp();
003610E3 FF 55 FC call dword ptr [jmp]
jmp_code_finish:;
return 0;
003610E6 33 C0 xor eax,eax
}
我试过这段代码,但出现错误:
int jmp_size = jmp_code_finish - jmp_code_start;
printf("jmp_size %d", jmp_size);
原源码为
#include <windows.h>
#include <stdio.h>
// 195 bytes small Windows/x86 null-free WinExec Calc.exe shellcode.
char shellcode[195] =
"\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b"
"\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3"
"\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24"
"\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14"
"\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18"
"\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74"
"\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41"
"\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52"
"\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51"
"\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff"
"\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f"
"\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2"
"\x52\xff\xd0";
int main(int argc, char* argv[])
{
jmp_code_start:;
char (*jmp)() = (char*)&main - sizeof(shellcode);
jmp();
jmp_code_finish:;
return 0;
}
根据提供的答案,下面的代码现在可以使用了!
#include <windows.h>
#include <stdio.h>
// 195 bytes small Windows/x86 null-free WinExec Calc.exe shellcode.
char shellcode[195] =
"\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b"
"\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3"
"\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24"
"\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14"
"\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18"
"\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74"
"\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41"
"\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52"
"\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51"
"\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff"
"\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f"
"\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2"
"\x52\xff\xd0";
void shellcode_func(void);
void dummy_function(void);
int main(int argc, char* argv[])
{
size_t jmp_size = (size_t)dummy_function - (size_t)shellcode_func;
return 0;
}
__declspec(naked) void shellcode_func(void) {
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
jmp();
}
void dummy_function(void) {}
警告
确定代码大小为 16 字节后,在其他地方使用该确切代码的大小可能会有所不同,即 17 字节。编译器选择使用哪些寄存器并直接影响生成的操作码字节数。
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
005E10D5 B9 C0 10 5E 00 mov ecx,offset main (05E10C0h)
005E10DA 81 E9 C0 00 00 00 sub ecx,0C0h
005E10E0 89 4D FC mov dword ptr [jmp],ecx
jmp();
005E10E3 FF 55 FC call dword ptr [jmp]
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
005E11B0 B8 C0 10 5E 00 mov eax,offset main (05E10C0h)
005E11B5 2D C0 00 00 00 sub eax,0C0h
005E11BA 89 45 FC mov dword ptr [jmp],eax
jmp();
005E11BD FF 55 FC call dword ptr [jmp]
在标准 C 中无法做到这一点。
但在实践中 - 您通常可以使用如下代码完成此操作:
__declspec(naked) void shellcode_func(void) {
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
jmp();
}
void dummy_function(void) {}
int main() {
size_t jmp_size = (size_t)dummy_function - (size_t)shellcode_func;
}
__declspec(naked)
属性(在 GCC 中可用作 __attribute__((naked))
)对于确保 shellcode 函数的定义没有函数序言或尾声是必要的 - 从而保持其原始大小(以字节为单位)。
GCC 和 Clang 有一个扩展来获取标签地址:
(char *)&&jmp_code_finish - (char *)&&jmp_code_start
基于这个 MSVC Windows 反汇编,有没有一种方法可以确定标签之间的字节数 jmp_code_start 和 jmp_code_finish?手动计算操作码字节 B8 D0 10 36 00 2D C3 00 00 00 89 45 FC FF 55 FC 显示有 16 个字节,但这很乏味。也许有更好的技术?
int main(int argc, char* argv[])
{
003610D0 66 90 xchg ax,ax
003610D2 55 push ebp
003610D3 8B EC mov ebp,esp
003610D5 51 push ecx
jmp_code_start:;
char (*jmp)() = (char*)&main - sizeof(shellcode);
003610D6 B8 D0 10 36 00 mov eax,offset main (03610D0h)
003610DB 2D C3 00 00 00 sub eax,0C3h
003610E0 89 45 FC mov dword ptr [jmp],eax
jmp();
003610E3 FF 55 FC call dword ptr [jmp]
jmp_code_finish:;
return 0;
003610E6 33 C0 xor eax,eax
}
我试过这段代码,但出现错误:
int jmp_size = jmp_code_finish - jmp_code_start;
printf("jmp_size %d", jmp_size);
原源码为
#include <windows.h>
#include <stdio.h>
// 195 bytes small Windows/x86 null-free WinExec Calc.exe shellcode.
char shellcode[195] =
"\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b"
"\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3"
"\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24"
"\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14"
"\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18"
"\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74"
"\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41"
"\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52"
"\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51"
"\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff"
"\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f"
"\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2"
"\x52\xff\xd0";
int main(int argc, char* argv[])
{
jmp_code_start:;
char (*jmp)() = (char*)&main - sizeof(shellcode);
jmp();
jmp_code_finish:;
return 0;
}
根据提供的答案,下面的代码现在可以使用了!
#include <windows.h>
#include <stdio.h>
// 195 bytes small Windows/x86 null-free WinExec Calc.exe shellcode.
char shellcode[195] =
"\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b"
"\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3"
"\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24"
"\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14"
"\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18"
"\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74"
"\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41"
"\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52"
"\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51"
"\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff"
"\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f"
"\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2"
"\x52\xff\xd0";
void shellcode_func(void);
void dummy_function(void);
int main(int argc, char* argv[])
{
size_t jmp_size = (size_t)dummy_function - (size_t)shellcode_func;
return 0;
}
__declspec(naked) void shellcode_func(void) {
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
jmp();
}
void dummy_function(void) {}
警告
确定代码大小为 16 字节后,在其他地方使用该确切代码的大小可能会有所不同,即 17 字节。编译器选择使用哪些寄存器并直接影响生成的操作码字节数。
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
005E10D5 B9 C0 10 5E 00 mov ecx,offset main (05E10C0h)
005E10DA 81 E9 C0 00 00 00 sub ecx,0C0h
005E10E0 89 4D FC mov dword ptr [jmp],ecx
jmp();
005E10E3 FF 55 FC call dword ptr [jmp]
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
005E11B0 B8 C0 10 5E 00 mov eax,offset main (05E10C0h)
005E11B5 2D C0 00 00 00 sub eax,0C0h
005E11BA 89 45 FC mov dword ptr [jmp],eax
jmp();
005E11BD FF 55 FC call dword ptr [jmp]
在标准 C 中无法做到这一点。
但在实践中 - 您通常可以使用如下代码完成此操作:
__declspec(naked) void shellcode_func(void) {
char (*jmp)();
jmp = (char*)&main - sizeof(shellcode);
jmp();
}
void dummy_function(void) {}
int main() {
size_t jmp_size = (size_t)dummy_function - (size_t)shellcode_func;
}
__declspec(naked)
属性(在 GCC 中可用作 __attribute__((naked))
)对于确保 shellcode 函数的定义没有函数序言或尾声是必要的 - 从而保持其原始大小(以字节为单位)。
GCC 和 Clang 有一个扩展来获取标签地址:
(char *)&&jmp_code_finish - (char *)&&jmp_code_start