vmprotect-3.5.1/unit-tests/intel_tests.cc

4494 lines
87 KiB
C++

#include "../runtime/crypto.h"
#include "../core/objects.h"
#include "../core/osutils.h"
#include "../core/streams.h"
#include "../core/core.h"
#include "../core/files.h"
#include "../core/processors.h"
#include "../core/pefile.h"
#include "../core/intel.h"
#include "testfileintel.h"
TEST(IntelTest, x86_AsmMarkers)
{
uint8_t buf[] = {
0x55, // 004B58EC push ebp
0x8B, 0xEC, // 004B58ED mov ebp, esp
0x6A, 0x00, // 004B58EF push 00
0x6A, 0x00, // 004B58F1 push 00
0x6A, 0x00, // 004B58F3 push 00
0x53, // 004B58F5 push ebx
0x8B, 0xD8, // 004B58F6 mov ebx, eax
0x33, 0xC0, // 004B58F8 xor eax, eax
0x55, // 004B58FA push ebp
0x68, 0xDA, 0x59, 0x4B, 0x00, // 004B58FB push 004B59DA
0x64, 0xFF, 0x30, // 004B5900 push dword ptr fs:[eax]
0x64, 0x89, 0x20, // 004B5903 mov fs:[eax], esp
0xEB, 0x10, // 004B5906 jmp 004B5918
0x56, 0x4D, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x00, // db 'VMProtect begin', 0
0x8D, 0x55, 0xFC, // 004B5918 lea edx, [ebp-04]
0x8B, 0x83,
0x8C, 0x03, 0x00, 0x00, // 004B591A mov eax, [ebx+0000038C]
0xE8, 0x0A, 0xE0, 0xFC, 0xFF, // 004B5920 call 00483930
0x8B, 0x45, 0xFC, // 004B5925 mov eax, [ebp-04]
0x33, 0xD2, // 004B5928 xor edx, edx
0xE8, 0xD4, 0xCB, 0xF5, 0xFF, // 004B592A call 00412504
0xB9, 0x11, 0x00, 0x00, 0x00, // 004B592F mov ecx, 00000011
0x99, // 004B5930 cdq
0xF7, 0xF9, // 004B5931 idiv ecx
0x83, 0xFA, 0x0D, // 004B5933 cmp edx, 0D
0x75, 0x2F, // 004B5936 jnz 004B596C
0x68, 0xE8, 0x59, 0x4B, 0x00, // 004B5938 push 004B59E8
0xE8, 0x81, 0xFC, 0xFF, 0xFF, // 004B593D call 004B55C8
0x8B, 0xD0, // 004B5942 mov edx, eax
0x8D, 0x45, 0xF8, // 004B5944 lea eax, [ebp-08]
0xE8, 0x6F, 0x10, 0xF5, 0xFF, // 004B5947 call 004069C0
0x8B, 0x45, 0xF8, // 004B594C mov eax, [ebp-08]
0x6A, 0x00, // 004B594F push 00
0x6A, 0xFF, // 004B5951 push -01
0x6A, 0xFF, // 004B5953 push -01
0x6A, 0x00, // 004B5955 push 00
0x0F, 0xB7, 0x0D,
0xFC, 0x59, 0x4B, 0x00, // 004B5957 movzx ecx, word ptr [004B59FC]
0xB2, 0x02, // 004B595E mov dl, 02
0xE8, 0xAA, 0x4A, 0xFB, 0xFF, // 004B5960 call 0046A414
0xEB, 0x4B, // 004B5965 jmp 004B59B7
0x68, 0x00, 0x5A, 0x4B, 0x00, // 004B5967 push 004B5A00
0xE8, 0x52, 0xFC, 0xFF, 0xFF, // 004B596C call 004B55C8
0x8B, 0xD0, // 004B5971 mov edx, eax
0x8D, 0x45, 0xF4, // 004B5973 lea eax, [ebp-0C]
0xE8, 0x40, 0x10, 0xF5, 0xFF, // 004B5976 call 004069C0
0x8B, 0x45, 0xF4, // 004B597B mov eax, [ebp-0C]
0x6A, 0x00, // 004B597E push 00
0x6A, 0xFF, // 004B5980 push -01
0x6A, 0xFF, // 004B5982 push -01
0x6A, 0x00, // 004B5984 push 00
0x0F, 0xB7, 0x0D,
0xFC, 0x59, 0x4B, 0x00, // 004B5986 movzx ecx, word ptr [004B59FC]
0xB2, 0x01, // 004B598D mov dl, 01
0xE8, 0x7B, 0x4A, 0xFB, 0xFF, // 004B598F call 0046A414
0x8B, 0x83,
0x8C, 0x03, 0x00, 0x00, // 004B5994 mov eax, [ebx+0000038C]
0x8B, 0x10, // 004B599A mov edx, [eax]
0xFF, 0x92,
0xE8, 0x00, 0x00, 0x00, // 004B599C call dword ptr [edx+000000E8]
0xEB, 0x0E, // 004B59A2 jmp 004B59B7
0x56, 0x4D, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x20, 0x65, 0x6E, 0x64, 0x00, // db 'VMProtect end', 00
0x33, 0xC0, // 004B59B2 xor eax, eax
0x5A, // 004B59B4 pop edx
0x59, // 004B59B5 pop ecx
0x59, // 004B59B6 pop ecx
0x64, 0x89, 0x10, // 004B59B7 mov fs:[eax], edx
0x68, 0xE1, 0x59, 0x4B, 0x00, // 004B59BA push 004B59E1
0x8D, 0x45, 0xF4, // 004B59BF lea eax, [ebp-0C]
0xBA, 0x02, 0x00, 0x00, 0x00, // 004B59C2 mov edx, 00000002
0xE8, 0x6B, 0x0E, 0xF5, 0xFF, // 004B59C7 call 0040683C
0x8D, 0x45, 0xFC, // 004B59CC lea eax, [ebp-04]
0xE8, 0x5B, 0x0E, 0xF5, 0xFF, // 004B59CF call 00406834
0xC3, // 004B59D4 ret
0xE9, 0xC1, 0xFD, 0xF4, 0xFF, // 004B59D5 jmp 004057A0
0xEB, 0xE3, // 004B59DA jmp 004B59C4
0x5B, // 004B59DC pop ebx
0x8B, 0xE5, // 004B59DD mov esp, ebp
0x5D, // 004B59DF pop ebp
0xC3, // 004B59E0 ret
0x90, 0x90, 0x90, 0x90
};
IntelFunction *func;
MapFunctionList *map_function_list;
MapFunction *map_function;
IntelCommand *command;
TestFile test_file(osDWord);
TestArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x004B58EC, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 73ul);
map_function_list = arch.map_function_list();
map_function = map_function_list->GetFunctionByName("VMProtectMarker1");
ASSERT_TRUE(map_function != NULL);
EXPECT_EQ(map_function->address(), 0x004B5906ull);
EXPECT_EQ(func->ReadFromFile(arch, map_function->address()), 45ul);
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
}
TEST(IntelTest, CompilerFunction_Delphi)
{
PEFile pf(NULL);
EXPECT_EQ(pf.Open("test-binaries/win32-app-delphi-i386", foRead), osSuccess);
EXPECT_EQ(pf.count(), 1ul);
PEArchitecture &arch = *pf.arch_pe();
IntelFunction command_list;
EXPECT_EQ(command_list.ReadFromFile(arch, 0x004BBC48), 17ul);
EXPECT_EQ(command_list.ReadFromFile(arch, 0x004B5A34), 2ul);
}
uint8_t char2hex(char d)
{
if ((d >= '0') && (d <= '9')) {
return (d - '0');
}
if ((d >= 'A') && (d <= 'F')) {
return (d - '7');
}
if ((d >= 'a') && (d <= 'f')) {
return (d - 'W');
}
return 0;
}
void ascii2hex(const char *inp, uint8_t *out, size_t size)
{
size_t i, j;
for (i=0, j=0; j<size/2; j++, i+=2) {
out[j] = (char2hex(inp[i]) << 4) + char2hex(inp[i+1]);
}
}
TEST(IntelTest, x86)
{
// TestFile test_file(osDWord);
TestFile test_file(osQWord);
IArchitecture &arch = *test_file.item(0);
IntelCommand intel_command(NULL, arch.cpu_address_size(), 0x401000);
size_t i, k, n;
FileStream fs;
bool status;
std::string line, udisstr, intel_str;
uint8_t dump[40], sse_preffix;
return;
status = fs.Open("test-binaries/intel-x64-opcodes.txt", fmOpenRead | fmShareDenyNone); //-V779
ASSERT_TRUE(status);
for (;;) {
if (!fs.ReadLine(line))
break;
i = line.find(' ');
if (i > 0) {
ascii2hex(line.c_str(), dump, i);
n = 0;
sse_preffix = 0;
for (k = 0; k < i/2; k++) {
if (dump[k] == 0xF2 || dump[k] == 0xF3 || (dump[k] == 0x66 && sse_preffix == 0))
sse_preffix = dump[k];
if (dump[k] == 0x26 ||
dump[k] == 0x2e ||
dump[k] == 0x36 ||
dump[k] == 0x3e ||
dump[k] == 0x64 ||
dump[k] == 0x65 ||
dump[k] == 0x66 ||
dump[k] == 0x67 ||
dump[k] == 0xF2 ||
dump[k] == 0xF3
) {
n++;
} else {
break;
}
}
// VMRUN is not decoded by udis when ud_set_vendor(&u, UD_VENDOR_INTEL) is called; not a bug
if (dump[n] == 0x0f && dump[n+1] == 0x01 && dump[n+2] >= 0xc0)
continue;
// Workarounds for UDIS bugs (low priority of fixing)
// UDIS workaround: mov invalid_CR, reg, mov reg, invalid_CR
if (dump[n] == 0x0f && (dump[n+1] == 0x20 || dump[n + 1] == 0x22)) {
unsigned cr = (dump[n+2] & 0x38) >> 3;
if (cr == 1 || (cr >= 5 && cr <= 7) || cr >= 9)
continue;
}
if (arch.cpu_address_size() == osQWord) {
if ((dump[n] >= 0x48 && dump[n] <= 0x4f && dump[n+1] == 0x6d)
|| (dump[n] == 0x48 && dump[n+1] == 0x6f)
|| (dump[n] == 0x9c)
|| (dump[n] == 0x9d)
)
continue;
}
//dprint((line.c_str()));
//dprint(("\n"));
test_file.OpenFromMemory(dump, (uint32_t)(i / 2));
udisstr = line.substr(i + 1);
try {
if (intel_command.ReadFromFile(arch) != i / 2) {
if (intel_command.type() == cmDB && (line.substr(i + 1, 2).compare("db") == 0 || udisstr.find("invalid") != udisstr.npos))
continue;
FAIL() << "Cannot disassemble:\nudis: '" << udisstr
<< "'\nintel_command: '" << intel_command.text() << "'\n" <<
"binary: " << line.substr(0, i);
}
} catch (std::runtime_error & e) {
FAIL() << "Exception '" << e.what() << "'\n" << "Input: " << line;
}
intel_str = intel_command.text();
std::transform(intel_str.begin(), intel_str.end(), intel_str.begin(), ::tolower);
if (intel_str.compare(udisstr) != 0) {
if (udisstr.find("invalid") != udisstr.npos && intel_command.type() == cmDB)
continue;
if (udisstr.find("rip+") != udisstr.npos) {
//dprint((line.c_str()));
//dprint(("\n"));
continue;
}
if (intel_command.type() == cmLoop ||
intel_command.type() == cmLoope ||
intel_command.type() == cmLoopne ||
intel_command.type() == cmJCXZ ||
intel_command.type() == cmJmp ||
intel_command.type() == cmCall ||
intel_command.type() == cmPusha ||
intel_command.type() == cmPopa ||
intel_command.type() == cmJmpWithFlag)
continue;
FAIL() << "Disasm error:\nudis: '" << udisstr
<< "'\nintel_command: '" << intel_str << "'\n" <<
"binary: " << line.substr(0, i);
}
}
}
};
TEST(IntelTest, x86_Disasm)
{
PEFile pf(NULL);
IntelFunction command_list;
EXPECT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
EXPECT_EQ(pf.count(), 1ul);
IArchitecture &arch = *pf.item(0);
EXPECT_EQ(command_list.ReadFromFile(arch, 0x00401198), 53ul);
EXPECT_TRUE(command_list.GetCommandByNearAddress(0x00401235) != NULL);
EXPECT_EQ(command_list.item(0)->address(), 0x00401198ull);
EXPECT_EQ(command_list.item(command_list.count() - 1)->next_address(), 0x00401240ull);
}
TEST(IntelTest, x86_DelphiSEH)
{
uint8_t buf[] = {
0x55, // push ebp
0x8B, 0xEC, // mov ebp, esp
0x83, 0xC4, 0xEC, // add esp, -14
0x53, // push ebx
0x56, // push esi
0x57, // push edi
0x33, 0xC0, // xor eax, eax
0x89, 0x45, 0xEC, // mov [ebp-14], eax
0xA1, 0x9C, 0x1D, 0x41, 0x00, // mov eax, [00411D9C]
0xC6, 0x00, 0x01, // mov byte ptr [eax], 01
0xB8, 0xB4, 0xE4, 0x40, 0x00, // mov eax, 0040E4B4
0xE8, 0x10, 0x89, 0xFF, 0xFF, // call 00408AA0
0x33, 0xC0, // xor eax, eax
0x55, // push ebp
0x68, 0x37, 0x02, 0x41, 0x00, // push 00410237
0x64, 0xFF, 0x30, // push dword ptr fs:[eax]
0x64, 0x89, 0x20, // mov fs:[eax], esp
0x33, 0xC0, // xor eax, eax
0x55, // push ebp
0x68, 0xD6, 0x01, 0x41, 0x00, // push 004101D6
0x64, 0xFF, 0x30, // push dword ptr fs:[eax]
0x64, 0x89, 0x20, // mov fs:[eax], esp
0xB8, 0x32, 0x00, 0x00, 0x00, // mov eax, 00000032
0xE8, 0x06, 0x3B, 0xFF, 0xFF, // call 00403CBC
0x8B, 0xD0, // mov edx, eax
0xA1, 0xE0, 0x1C, 0x41, 0x00, // mov eax, [00411CE0]
0xE8, 0x72, 0x42, 0xFF, 0xFF, // call 00404434
0xE8, 0x99, 0x42, 0xFF, 0xFF, // call 00404460
0xE8, 0xA0, 0x39, 0xFF, 0xFF, // call 00403B6C
0x33, 0xC0, // xor eax, eax
0x5A, // pop edx
0x59, // pop ecx
0x59, // pop ecx
0x64, 0x89, 0x10, // mov fs:[eax], edx
0xEB, 0x4B, // jmp 00410221
0xE9, 0x21, 0x4F, 0xFF, 0xFF, // jmp 004050FC
0x01, 0x00, 0x00, 0x00, // dd 00000001
0x54, 0x90, 0x41, 0x00, // dd 00419054
0xE7, 0x01, 0x41, 0x00, // dd 004101E7
0x8B, 0xD8, // mov ebx, eax
0x8D, 0x55, 0xEC, // lea edx, [ebp-14]
0x8B, 0x03, // mov eax, [ebx]
0xE8, 0xBD, 0x45, 0xFF, 0xFF, // call 004047B0
0x8B, 0x55, 0xEC, // mov edx, [ebp-14]
0xA1, 0xE0, 0x1C, 0x41, 0x00, // mov eax, [00411CE0]
0xE8, 0x8C, 0x64, 0xFF, 0xFF, // call 0040668C
0xBA, 0x54, 0x02, 0x41, 0x00, // mov edx, 00410254
0xE8, 0x82, 0x64, 0xFF, 0xFF, // call 0040668C
0x8B, 0x53, 0x04, // mov edx, [ebx+04]
0xE8, 0x7A, 0x64, 0xFF, 0xFF, // call 0040668C
0xE8, 0x49, 0x42, 0xFF, 0xFF, // call 00404460
0xE8, 0x50, 0x39, 0xFF, 0xFF, // call 00403B6C
0xE8, 0x07, 0x52, 0xFF, 0xFF, // call 00405428
0x33, 0xC0, // xor eax, eax
0x5A, // pop edx
0x59, // pop ecx
0x59, // pop ecx
0x64, 0x89, 0x10, // mov fs:[eax], edx
0x68, 0x3E, 0x02, 0x41, 0x00, // push 0041023E
0x8D, 0x45, 0xEC, // lea eax, [ebp-14]
0xE8, 0x66, 0x5E, 0xFF, 0xFF, // call 0040609C
0xC3, // ret
0xE9, 0x48, 0x50, 0xFF, 0xFF, // jmp 00405284
0xEB, 0xF0, // jmp 0041022E
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0xE8, 0xF6, 0x56, 0xFF, 0xFF, // call 0040593C
0xC3 // ret
};
ICommand *command;
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00410170, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
EXPECT_EQ(func->count(), 69ul);
command = func->GetCommandByAddress(0x004101a1);
EXPECT_EQ(command->link()->type(), ltFilterSEHBlock);
command = func->GetCommandByAddress(0x004101DB);
EXPECT_EQ(command->text(), "dd 00000001");
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 00419054");
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 004101E7");
EXPECT_EQ(command->link()->type(), ltMemSEHBlock);
command = func->GetCommandByAddress(0x00410229);
EXPECT_EQ(command->link()->type(), ltFinallyBlock);
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
// Check the compilation prepare
MemoryManager manager(&arch);
CompileContext ctx;
ctx.file = &arch;
ctx.manager = &manager;
ASSERT_TRUE(func->Prepare(ctx));
ASSERT_TRUE(func->PrepareExtCommands(ctx));
ASSERT_EQ(manager.count(), 2ul);
MemoryRegion *region = manager.item(0);
EXPECT_EQ(region->address(), 0x00410175ull);
EXPECT_EQ(region->size(), 0x66ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
region = manager.item(1);
EXPECT_EQ(region->address(), 0x004101e7ull);
EXPECT_EQ(region->size(), 0x60ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
}
TEST(IntelTest, x86_ParseSDK)
{
PEFile pf(NULL);
IntelFunction *func;
MapFunctionList *map_function_list;
MapFunction *map_function;
IntelCommand *command;
EXPECT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
EXPECT_EQ(pf.count(), 1ul);
IArchitecture &arch = *pf.item(0);
map_function_list = arch.map_function_list();
map_function = map_function_list->GetFunctionByAddress(0x004011A3);
EXPECT_EQ(map_function->name().compare("VMProtectMarker \"Test marker\""), 0);
map_function = map_function_list->GetFunctionByAddress(0x00403049);
EXPECT_EQ(map_function->name().compare("string \"Correct password\""), 0);
map_function = map_function_list->GetFunctionByAddress(0x00403066);
EXPECT_EQ(map_function->name().compare("string \"Incorrect password\""), 0);
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(0x004011A3, ctVirtualization, 0, true, NULL));
EXPECT_EQ(func->count(), 47ul);
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
}
TEST(IntelTest, Clone)
{
PEFile pf(NULL);
ASSERT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
EXPECT_EQ(pf.count(), 1ul);
IFunctionList *function_list = pf.item(0)->function_list();
Folder *f1 = pf.folder_list()->Add("Folder1");
Folder *f2 = f1->Add("Folder2");
IFunction *func = function_list->AddByAddress(0x004011A3, ctUltra, 0, false, f2);
size_t command_count = func->count();
size_t link_count = func->link_list()->count();
uint64_t link_address = func->link_list()->item(2)->from_command()->address();
IFunctionList *clone_function_list = function_list->Clone(NULL);
pf.Close();
// Check clone function list.
//EXPECT_EQ(clone_function_list->root_folder()->count(), 1);
//EXPECT_EQ(clone_function_list->root_folder()->item(0)->count(), 1);
//EXPECT_EQ(clone_function_list->root_folder()->item(0)->name().compare("Folder1"), 0);
ASSERT_EQ(clone_function_list->count(), 1ul);
func = clone_function_list->item(0);
EXPECT_EQ(func->compilation_type(), ctUltra);
EXPECT_EQ(func->need_compile(), false);
//EXPECT_EQ(func->folder()->name().compare("Folder2"), 0);
ASSERT_EQ(func->count(), command_count);
ASSERT_EQ(func->link_list()->count(), link_count);
EXPECT_EQ(func->link_list()->item(2)->from_command()->address(), link_address);
delete clone_function_list;
}
TEST(IntelTest, x86_Switch)
{
uint8_t buf[] = {
0x83, 0xEC, 0x0C, // sub esp, 0C
0x53, // push ebx
0x56, // push esi
0x57, // push edi
0x89, 0x65, 0xE8, // mov [ebp-18], esp
0x8B, 0xF1, // mov esi, ecx
0x33, 0xC0, // xor eax, eax
0x89, 0x45, 0xE4, // mov [ebp-1C], eax
0x89, 0x45, 0xFC, // mov [ebp-04], eax
0x52, // push edx
0x51, // push ecx
0x53, // push ebx
0xB8, 0x68, 0x58, 0x4D, 0x56, // mov eax, 564D5868
0x33, 0xDB, // xor ebx, ebx
0xB9, 0x0A, 0x00, 0x00, 0x00, // mov ecx, 0000000A
0xBA, 0x58, 0x56, 0x00, 0x00, // mov edx, 00005658
0xED, // in eax, dx
0x81, 0xFB, 0x68, 0x58, 0x4D, 0x56, // cmp ebx, 564D5868
0x75, 0x03, // jnz 00403050
0x89, 0x4D, 0xE4, // mov [ebp-1C], ecx
0x5B, // pop ebx
0x59, // pop ecx
0x5A, // pop edx
0x8B, 0x45, 0xE4, // mov eax, [ebp-1C]
0x48, // dec eax
0x83, 0xF8, 0x03, // cmp eax, 03
0x0F, 0x87, 0x97, 0x00, 0x00, 0x00, // jnbe 004030F7
0xFF, 0x24, 0x85, 0x40, 0x31, 0x40, 0x00, // jmp dword ptr [eax*4+00403140]
0x68, 0x74, 0xD8, 0x4E, 0x00, // push 004ED874
0xE8, 0xDF, 0x00, 0x00, 0x00, // call 00403150
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB0, 0x01, // mov al, 01
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0x68, 0x94, 0xD8, 0x4E, 0x00, // push 004ED894
0xE8, 0xBB, 0x00, 0x00, 0x00, // call 00403150
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB0, 0x01, // mov al, 01
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0x68, 0xB8, 0xD8, 0x4E, 0x00, // push 004ED8B8
0xE8, 0x97, 0x00, 0x00, 0x00, // call 00403150
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB0, 0x01, // mov al, 01
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0x68, 0xDC, 0xD8, 0x4E, 0x00, // push 004ED8DC
0xE8, 0x73, 0x00, 0x00, 0x00, // call 00403150
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB0, 0x01, // mov al, 01
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0x68, 0x04, 0xD9, 0x4E, 0x00, // push 004ED904
0xE8, 0x4F, 0x00, 0x00, 0x00, // call 00403150
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB0, 0x01, // mov al, 01
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 00000001
0xC3, // ret
0x8B, 0x65, 0xE8, // mov esp, [ebp-18]
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0x32, 0xC0, // xor al, al
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0xCD, 0xCD, // alignment
0x67, 0x30, 0x40, 0x00, // dd 00403067
0x8B, 0x30, 0x40, 0x00, // dd 0040308B
0xAF, 0x30, 0x40, 0x00, // dd 004030AF
0xD3, 0x30, 0x40, 0x00, // dd 004030D3
0x00, 0x00, 0x00, 0x00 // dd 0
};
ICommand *command;
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x0040301D, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 92ul);
command = func->GetCommandByAddress(0x00403140);
EXPECT_EQ(command->text(), "dd 00403067");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 0040308B");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 004030AF");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 004030D3");
EXPECT_EQ(command->link()->type(), ltCase);
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
// Check the compilation prepare
MemoryManager manager(&arch);
CompileContext ctx;
ctx.file = &arch;
ctx.manager = &manager;
ASSERT_TRUE(func->Prepare(ctx));
ASSERT_TRUE(func->PrepareExtCommands(ctx));
ASSERT_EQ(manager.count(), 2ul);
MemoryRegion *region = manager.item(0);
EXPECT_EQ(region->address(), 0x00403022ull);
EXPECT_EQ(region->size(), 0xF9ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
region = manager.item(1);
EXPECT_EQ(region->address(), 0x00403140ull);
EXPECT_EQ(region->size(), 0x10ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
}
TEST(IntelTest, x86_MsvcSEH)
{
uint8_t buf[] = {
0x55, // push ebp
0x8B, 0xEC, // mov ebp, esp
0x6A, 0xFF, // push -01
0x68, 0x48, 0x32, 0x40, 0x00, // push 00403248
0x68, 0xE4, 0x7A, 0x4D, 0x00, // push 004D7AE4
0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, // mov eax, fs:[00000000]
0x50, // push eax
0x64, 0x89, 0x25, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], esp
0x83, 0xEC, 0x08, // sub esp, 08
0x53, // push ebx
0x56, // push esi
0x57, // push edi
0x89, 0x65, 0xE8, // mov [ebp-18], esp
0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, // mov dword ptr [ebp-04], 00000000
0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 00000001
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nop
0x68, 0x14, 0xD9, 0x4E, 0x00, // push 004ED914
0x8B, 0xF1, // mov esi, ecx
0xE8, 0x47, 0xFF, 0xFF, 0xFF, // call 00403150
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB0, 0x01, // mov al, 01
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 00000001
0xC3, // ret
0x8B, 0x65, 0xE8, // mov esp, [ebp-18]
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0x32, 0xC0, // xor al, al
0x8B, 0x4D, 0xF0, // mov ecx, [ebp-10]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0xCD, 0xCD, // alignment
0xFF, 0xFF, 0xFF, 0xFF, // dd FFFFFFFF
0x23, 0x32, 0x40, 0x00, // dd 00403223
0x29, 0x32, 0x40, 0x00, // dd 00403229
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00 // dd 0
};
ICommand *command;
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x004031C0, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 55ul);
command = func->GetCommandByAddress(0x00403248);
EXPECT_EQ(command->text(), "dd FFFFFFFF");
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 00403223");
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 00403229");
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
// Check the compilation prepare
MemoryManager manager(&arch);
CompileContext ctx;
ctx.file = &arch;
ctx.manager = &manager;
ASSERT_TRUE(func->Prepare(ctx));
ASSERT_TRUE(func->PrepareExtCommands(ctx));
ASSERT_EQ(manager.count(), 1ul);
MemoryRegion *region = manager.item(0);
EXPECT_EQ(region->address(), 0x004031C5ull);
EXPECT_EQ(region->size(), 0x81ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
}
TEST(IntelTest, x64_Switch)
{
uint8_t buf[] = {
0x83, 0xFB, 0x06, // cmp ebx, 06
0x74, 0x0A, // jz 000000010001874A
0x83, 0xFB, 0x07, // cmp ebx, 07
0x74, 0x05, // jz 000000010001874A
0x83, 0xFB, 0x08, // cmp ebx, 08
0x75, 0x35, // jnz 000000010001877F
0xBA, 0x04, 0xE8, 0x00, 0x00, // mov edx, 0000E804
0xE8, 0xBA, 0x2B, 0x01, 0x00, // call 000000010002B30E
0x48, 0x85, 0xC0, // test rax, rax
0x74, 0x0A, // jz 0000000100018763
0x33, 0xD2, // xor edx, edx
0x48, 0x8B, 0xC8, // mov rcx, rax
0xE8, 0x17, 0x20, 0x01, 0x00, // call 000000010002A77A
0xBA, 0x05, 0xE8, 0x00, 0x00, // mov edx, 0000E805
0x48, 0x8B, 0xCF, // mov rcx, rdi
0xE8, 0x9E, 0x2B, 0x01, 0x00, // call 000000010002B30E
0x48, 0x85, 0xC0, // test rax, rax
0x74, 0x0A, // jz 000000010001877F
0x33, 0xD2, // xor edx, edx
0x48, 0x8B, 0xC8, // mov rcx, rax
0xE8, 0xFB, 0x1F, 0x01, 0x00, // call 000000010002A77A
0x8D, 0x43, 0xFF, // lea eax, [rbx-01]
0x83, 0xF8, 0x09, // cmp eax, 09
0x77, 0x27, // jnbe 00000001000187AE
0x48, 0x8D, 0x15, 0x72, 0x78, 0xFE, 0xFF, // lea rdx, [0000000100000000]
0x48, 0x98, // cdqe
0x8B, 0x8C, 0x82, 0xF8, 0x87, 0x01, 0x00, // mov ecx, [rdx+rax*4+00000000000187F8]
0x48, 0x03, 0xCA, // add rcx, rdx
0xFF, 0xE1, // jmp rcx
0x4C, 0x8B, 0x8F, 0x58, 0x01, 0x00, 0x00, // mov r9, [rdi+0000000000000158]
0xEB, 0x10, // jmp 00000001000187B5
0x4C, 0x8B, 0x8F, 0x60, 0x01, 0x00, 0x00, // mov r9, [rdi+0000000000000160]
0xEB, 0x07, // jmp 00000001000187B5
0x4C, 0x8B, 0x8F, 0x50, 0x01, 0x00, 0x00, // mov r9, [rdi+0000000000000150]
0x48, 0x8B, 0x4F, 0x40, // mov rcx, [rdi+40]
0xBA, 0x80, 0x00, 0x00, 0x00, // mov edx, 00000080
0x44, 0x8D, 0x42, 0x81, // lea r8d, [rdx-7F]
0xFF, 0x15, 0xA8, 0xA2, 0xFE, 0xFF, // call qword ptr [0000000100002A70]
0x48, 0x8D, 0x0D, 0x81, 0x77, 0x02, 0x00, // lea rcx, [000000010003FF50]
0x41, 0xB8, 0x01, 0x00, 0x00, 0x00, // mov r8d, 00000001
0x8B, 0xD3, // mov edx, ebx
0xE8, 0xD4, 0x77, 0x00, 0x00, // call 000000010001FFB0
0x48, 0x8B, 0xCF, // mov rcx, rdi
0x48, 0x8B, 0xD0, // mov rdx, rax
0xE8, 0x87, 0x28, 0x01, 0x00, // call 000000010002B06E
0x48, 0x8B, 0x7C, 0x24, 0x48, // mov rdi, [rsp+48]
0x48, 0x8B, 0x5C, 0x24, 0x40, // mov rbx, [rsp+40]
0x33, 0xC0, // xor eax, eax
0x48, 0x83, 0xC4, 0x28, // add rsp, 28
0xC3, // ret
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0xA5, 0x87, 0x01, 0x00, // dd 000187A5
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0x9C, 0x87, 0x01, 0x00, // dd 0001879C
0x9C, 0x87, 0x01, 0x00, // dd 0001879C
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0xAE, 0x87, 0x01, 0x00, // dd 000187AE
0x00, 0x00, 0x00, 0x00 // dd 0
};
ICommand *command;
IntelFunction *func;
TestFile test_file(osQWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x010001873Bull, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
EXPECT_EQ(func->count(), 60ul);
command = func->GetCommandByAddress(0x01000187F8ull);
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187A5");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 0001879C");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 0001879C");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
command = func->GetCommandByAddress(command->next_address());
EXPECT_EQ(command->text(), "dd 000187AE");
EXPECT_EQ(command->link()->type(), ltCase);
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
// Check the compilation prepare
MemoryManager manager(&arch);
CompileContext ctx;
ctx.file = &arch;
ctx.manager = &manager;
ASSERT_TRUE(func->Prepare(ctx));
ASSERT_TRUE(func->PrepareExtCommands(ctx));
ASSERT_EQ(manager.count(), 1ul);
MemoryRegion *region = manager.item(0);
EXPECT_EQ(region->address(), 0x0100018740ull);
EXPECT_EQ(region->size(), 0xe0ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
}
TEST(IntelTest, x86_MsvcSEH2)
{
uint8_t buf[] = {
0x55, // push ebp
0x8B, 0xEC, // mov ebp, esp
0x6A, 0xFF, // push -01
0x68, 0x7E, 0x10, 0x40, 0x00, // push 0040107E
0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, // mov eax, fs:[00000000]
0x50, // push eax
0x51, // push ecx
0x53, // push ebx
0x56, // push esi
0x57, // push edi
0xA1, 0x00, 0x30, 0x40, 0x00, // mov eax, [00403000]
0x33, 0xC5, // xor eax, ebp
0x50, // push eax
0x8D, 0x45, 0xF4, // lea eax, [ebp-0C]
0x64, 0xA3, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], eax
0x89, 0x65, 0xF0, // mov [ebp-10], esp
0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, // mov dword ptr [ebp-04], 00000000
0x8B, 0x45, 0x08, // mov eax, [ebp+08]
0x99, // cdq
0x33, 0xC9, // xor ecx, ecx
0xF7, 0xF9, // idiv ecx
0x85, 0xC0, // test eax, eax
0x75, 0x0E, // jnz 0040104A
0x68, 0xF4, 0x20, 0x40, 0x00, // push 004020F4
0xFF, 0x15, 0xA0, 0x20, 0x40, 0x00, // call dword ptr [004020A0]
0x83, 0xC4, 0x04, // add esp, 04
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0x8B, 0x4D, 0xF4, // mov ecx, [ebp-0C]
0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov fs:[00000000], ecx
0x59, // pop ecx
0x5F, // pop edi
0x5E, // pop esi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp, ebp
0x5D, // pop ebp
0xC3, // ret
0x68, 0x00, 0x21, 0x40, 0x00, // push 00402100
0xFF, 0x15, 0xA0, 0x20, 0x40, 0x00, // call dword ptr [004020A0]
0x83, 0xC4, 0x04, // add esp, 04
0xC7, 0x45, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, // mov dword ptr [ebp-04], FFFFFFFF
0xB8, 0x51, 0x10, 0x40, 0x00, // mov eax, 00401051
0xC3, // ret
0x8B, 0x54, 0x24, 0x08, // mov edx, [esp+08]
0x8D, 0x42, 0x0C, // lea eax, [edx+0C]
0x8B, 0x4A, 0xEC, // mov ecx, [edx-14]
0x33, 0xC8, // xor ecx, eax
0xE8, 0xE3, 0xF7, 0xFF, 0xFF, // call 00401094
0xB8, 0xD0, 0x10, 0x40, 0x00, // mov eax, 004010D0
0xE9, 0xD3, 0xFF, 0xFF, 0xFF, // jmp 0040188E
0xCD, 0xCD, 0xCD, // alignment
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x63, 0x10, 0x40, 0x00, // dd 00401063
0xFF, 0xFF, 0xFF, 0xFF, // dd FFFFFFFF
0x00, 0x00, 0x00, 0x00, // dd 00000000
0xFF, 0xFF, 0xFF, 0xFF, // dd FFFFFFFF
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x01, 0x00, 0x00, 0x00, // dd 00000001
0x01, 0x00, 0x00, 0x00, // dd 00000001
0x9C, 0x10, 0x40, 0x00, // dd 0040109C
0x22, 0x05, 0x93, 0x19, // dd 19930522
0x02, 0x00, 0x00, 0x00, // dd 00000002
0xAC, 0x10, 0x40, 0x00, // dd 004010AC
0x01, 0x00, 0x00, 0x00, // dd 00000001
0xBC, 0x10, 0x40, 0x00, // dd 004010BC
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
0x00, 0x00, 0x00, 0x00, // dd 00000000
};
ICommand *command;
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 64ul);
command = func->GetCommandByAddress(0x004010a8);
EXPECT_EQ(command->text(), "dd 00401063");
EXPECT_EQ(command->link()->type(), ltExtSEHHandler);
// Check CompileToNative
std::vector<uint8_t> data;
size_t i, j;
for (i = 0; i < func->count(); i++) {
command = func->item(i);
if ((command->type() == cmJmpWithFlag || command->type() == cmJmp || command->type() == cmCall) && command->dump_size() == 2)
continue;
data.clear();
for (j = 0; j < command->dump_size(); j++) {
data.push_back(command->dump(j));
}
command->CompileToNative();
EXPECT_EQ(command->dump_size(), data.size());
for (j = 0; j < command->dump_size(); j++) {
EXPECT_EQ(command->dump(j), data[j]);
}
}
// Check the compilation prepare
MemoryManager manager(&arch);
CompileContext ctx;
ctx.file = &arch;
ctx.manager = &manager;
ASSERT_TRUE(func->Prepare(ctx));
ASSERT_TRUE(func->PrepareExtCommands(ctx));
ASSERT_EQ(manager.count(), 1ul);
MemoryRegion *region = manager.item(0);
EXPECT_EQ(region->address(), 0x00401005ull);
EXPECT_EQ(region->size(), 0x79ul);
EXPECT_EQ((int)region->type(), (mtReadable | mtExecutable));
}
TEST(IntelTest, x86_FPU)
{
uint8_t buf[] = {
0x9B, 0xD9, 0x7D, 0xFC, // fstcw [ebp - 4]
0x9B, 0xDD, 0x7D, 0xFC, // fstsw [ebp - 4]
0x9B, // wait
0x90, // nop
0xD9, 0x7D, 0xFC, // fnstcw [ebp - 4]
0xDD, 0x7D, 0xFC, // fnstsw [ebp - 4]
0xC3, // ret
0xCD, 0xCD, 0xCD, 0xCD, // alignment
};
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 7ul);
EXPECT_EQ(func->item(0)->text(), "fstcw word ptr [ebp-04]");
EXPECT_EQ(func->item(1)->text(), "fstsw word ptr [ebp-04]");
EXPECT_EQ(func->item(4)->text(), "fnstcw word ptr [ebp-04]");
EXPECT_EQ(func->item(5)->text(), "fnstsw word ptr [ebp-04]");
}
TEST(IntelTest, x86_DisasmBranch1)
{
uint8_t buf[] = {
0x90, // nop
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0xC3, // ret
};
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 2ul);
}
TEST(IntelTest, x86_DisasmBranch2)
{
uint8_t buf[] = {
0x90, // nop
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0x90, // nop
0x90, // nop
0x90, // nop
0x90, // nop
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0x0F, 0x84, 0xF3, 0xFF, 0xFF, 0xFF, // jz -13
0x90, // nop
0xC3, // ret
};
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 2ul);
}
TEST(IntelTest, x86_DisasmBranch3)
{
uint8_t buf[] = {
0x90, // nop
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0x90, // nop
0x0F, 0x84, 0xF2, 0xFF, 0xFF, 0xFF, // jz -14
0x90, // nop
0x90, // nop
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0x0F, 0x84, 0xF3, 0xFF, 0xFF, 0xFF, // jz -13
0x90, // nop
0xC3, // ret
};
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 10ul);
}
TEST(IntelTest, x86_DisasmBranch4)
{
uint8_t buf[] = {
0x90, // nop
0xE9, 0x03, 0x00, 0x00, 0x00, // jmp +3
0xCC, // --
0x90, // nop
0x90, // nop
0x90, // nop
0x90, // nop
0x0F, 0x84, 0xF6, 0xFF, 0xFF, 0xFF, // jz -10
0x90, // nop
0x90, // nop
0xE9, 0x01, 0x00, 0x00, 0x00, // jmp +1
0xCC, // --
0x0F, 0x84, 0xF3, 0xFF, 0xFF, 0xFF, // jz -13
0x90, // nop
0xC3, // ret
};
IntelFunction *func;
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(0x00401000, 0x10000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(sizeof(buf));
test_file.OpenFromMemory(buf, sizeof(buf));
func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment_list->item(0)->address(), ctVirtualization, 0, true, NULL));
ASSERT_EQ(func->count(), 13ul);
}
#ifdef _WIN32
void CompileFunction(void *src, void *dest)
{
uint8_t *buf = reinterpret_cast<uint8_t *>(src);
if (buf[0] == 0xe9) {
// jmp
uint32_t dw = *reinterpret_cast<uint32_t*>(&buf[1]);
buf = &buf[dw + 5];
}
TestFile test_file(osDWord);
IArchitecture &arch = *test_file.item(0);
TestSegmentList *segment_list = reinterpret_cast<TestSegmentList *>(arch.segment_list());
TestSegment *segment = segment_list->Add(reinterpret_cast<uint64_t>(dest), 0x1000, ".text", mtReadable | mtExecutable);
segment->set_physical_size(static_cast<uint32_t>(segment->size()));
test_file.OpenFromMemory(buf, static_cast<uint32_t>(0x1000 - 0x100));
IntelFunction *func = reinterpret_cast<IntelFunction *>(arch.function_list()->AddByAddress(segment->address(), ctVirtualization, 0, true, NULL));
for (size_t i = 0; i < func->count(); i++) {
IntelCommand *command = func->item(i);
if (command->type() == cmCall)
command->set_operand_value(0, command->operand(0).value + reinterpret_cast<uint64_t>(buf) - reinterpret_cast<uint64_t>(dest));
}
CompileOptions options;
options.flags = cpEncryptBytecode;
//int r = GetTickCount();
//printf("%d\n", r);
//srand(r);
arch.Compile(options, NULL);
arch.Seek(0);
arch.Read(dest, (size_t)arch.size());
}
void DoTestFunctionDWord(void *func_)
{
void *address = VirtualAlloc(NULL, 0x20000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ASSERT_TRUE(address != NULL);
CompileFunction(func_, address);
uint32_t orig_flags, flags;
uint32_t param1, param2, orig_res, res;
for (size_t i = 0; i < 100; i++) {
param1 = rand32();
param2 = rand32();
typedef uint32_t (tFunc)(uint32_t param1, uint32_t param2, uint32_t *flags);
orig_res = reinterpret_cast<tFunc *>(func_)(param1, param2, &orig_flags);
res = reinterpret_cast<tFunc *>(address)(param1, param2, &flags);
EXPECT_EQ(res, orig_res);
EXPECT_EQ(flags, orig_flags);
}
VirtualFree(address, 0, MEM_RELEASE);
}
void DoTestFunctionWord(void *func)
{
void *address = VirtualAlloc(NULL, 0x20000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ASSERT_TRUE(address != NULL);
CompileFunction(func, address);
uint32_t orig_flags, flags;
uint16_t param1, param2, orig_res, res;
for (size_t i = 0; i < 100; i++) {
param1 = rand();
param2 = rand();
typedef uint16_t (tFunc)(uint16_t param1, uint16_t param2, uint32_t *flags);
orig_res = reinterpret_cast<tFunc *>(func)(param1, param2, &orig_flags);
res = reinterpret_cast<tFunc *>(address)(param1, param2, &flags);
EXPECT_EQ(res, orig_res);
EXPECT_EQ(flags, orig_flags);
}
VirtualFree(address, 0, MEM_RELEASE);
}
void DoTestFunctionByte(void *func)
{
void *address = VirtualAlloc(NULL, 0x20000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ASSERT_TRUE(address != NULL);
CompileFunction(func, address);
uint32_t orig_flags, flags;
uint8_t param1, param2, orig_res;
for (size_t i = 0; i < 100; i++) {
param1 = rand();
param2 = rand();
typedef uint8_t (tFunc)(uint8_t param1, uint8_t param2, uint32_t *flags);
orig_res = reinterpret_cast<tFunc *>(func)(param1, param2, &orig_flags);
EXPECT_EQ(reinterpret_cast<tFunc *>(address)(param1, param2, &flags), orig_res);
EXPECT_EQ(flags, orig_flags);
}
VirtualFree(address, 0, MEM_RELEASE);
}
#ifndef _WIN64
uint32_t AddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
add eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t AddWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
add ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t AddByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
add al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationAdd)
{
DoTestFunctionDWord(&AddDWord);
DoTestFunctionWord(&AddWord);
DoTestFunctionByte(&AddByte);
}
uint32_t AdcDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
adc eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t AdcWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
adc ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t AdcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
adc al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationAdc)
{
DoTestFunctionDWord(&AdcDWord);
DoTestFunctionWord(&AdcWord);
DoTestFunctionByte(&AdcByte);
}
uint32_t SubDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
sub eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t SubWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
sub ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t SubByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
sub al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationSub)
{
DoTestFunctionDWord(&SubDWord);
DoTestFunctionWord(&SubWord);
DoTestFunctionByte(&SubByte);
}
uint32_t SbbDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
sbb eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t SbbWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
sbb ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t SbbByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
sbb al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationSbb)
{
DoTestFunctionDWord(&SbbDWord);
DoTestFunctionWord(&SbbWord);
DoTestFunctionByte(&SbbByte);
}
uint32_t CmpDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t CmpWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t CmpByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationCmp)
{
DoTestFunctionDWord(&CmpDWord);
DoTestFunctionWord(&CmpWord);
DoTestFunctionByte(&CmpByte);
}
uint32_t ShlDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
shl eax, cl
mov res, eax
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t ShlWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
shl ax, cl
mov res, ax
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t ShlByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
shl al, cl
mov res, al
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationShl)
{
DoTestFunctionDWord(&ShlDWord);
DoTestFunctionWord(&ShlWord);
DoTestFunctionByte(&ShlByte);
}
uint32_t ShrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
shr eax, cl
mov res, eax
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t ShrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
shr ax, cl
mov res, ax
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t ShrByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
shr al, cl
mov res, al
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationShr)
{
DoTestFunctionDWord(&ShrDWord);
DoTestFunctionWord(&ShrWord);
DoTestFunctionByte(&ShrByte);
}
uint32_t RolDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
rol eax, cl
mov res, eax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t RolWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
rol ax, cl
mov res, ax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t RolByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
rol al, cl
mov res, al
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationRol)
{
DoTestFunctionDWord(&RolDWord);
DoTestFunctionWord(&RolWord);
DoTestFunctionByte(&RolByte);
}
uint32_t RorDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
ror eax, cl
mov res, eax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t RorWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
ror ax, cl
mov res, ax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t RorByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
ror al, cl
mov res, al
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationRor)
{
DoTestFunctionDWord(&RorDWord);
DoTestFunctionWord(&RorWord);
DoTestFunctionByte(&RorByte);
}
uint32_t SarDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
sar eax, cl
mov res, eax
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t SarWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
sar ax, cl
mov res, ax
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t SarByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
sar al, cl
mov res, al
pushfd
pop eax
and eax, ~fl_A
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationSar)
{
DoTestFunctionDWord(&SarDWord);
DoTestFunctionWord(&SarWord);
DoTestFunctionByte(&SarByte);
}
uint32_t RclDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
rcl eax, cl
mov res, eax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t RclWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
rcl ax, cl
mov res, ax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t RclByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
rcl al, cl
mov res, al
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationRcl)
{
DoTestFunctionDWord(&RclDWord);
DoTestFunctionWord(&RclWord);
DoTestFunctionByte(&RclByte);
}
uint32_t RcrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
rcr eax, cl
mov res, eax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t RcrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
rcr ax, cl
mov res, ax
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t RcrByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
rcr al, cl
mov res, al
pushfd
pop eax
and cl, 31
jnz label_1
xor eax, eax
label_1:
cmp cl, 1
jz label_2
and eax, ~fl_O
label_2:
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationRcr)
{
DoTestFunctionDWord(&RcrDWord);
DoTestFunctionWord(&RcrWord);
DoTestFunctionByte(&RcrByte);
}
uint32_t XorDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
xor eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t XorWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
xor ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t XorByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
xor al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationXor)
{
DoTestFunctionDWord(&XorDWord);
DoTestFunctionWord(&XorWord);
DoTestFunctionByte(&XorByte);
}
uint32_t OrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
or eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t OrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
or ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t OrByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
or al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationOr)
{
DoTestFunctionDWord(&OrDWord);
DoTestFunctionWord(&OrWord);
DoTestFunctionByte(&OrByte);
}
uint32_t AndDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
and eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t AndWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
and ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t AndByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
and al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationAnd)
{
DoTestFunctionDWord(&AndDWord);
DoTestFunctionWord(&AndWord);
DoTestFunctionByte(&AndByte);
}
uint32_t TestDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
test eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t TestWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
test ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t TestByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
test al, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationTest)
{
DoTestFunctionDWord(&TestDWord);
DoTestFunctionWord(&TestWord);
DoTestFunctionByte(&TestByte);
}
uint32_t NotDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
not eax
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t NotWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
not ax
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t NotByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
not al
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationNot)
{
DoTestFunctionDWord(&NotDWord);
DoTestFunctionWord(&NotWord);
DoTestFunctionByte(&NotByte);
}
uint32_t NegDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
neg eax
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t NegWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
neg ax
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t NegByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
neg al
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationNeg)
{
DoTestFunctionDWord(&NegDWord);
DoTestFunctionWord(&NegWord);
DoTestFunctionByte(&NegByte);
}
uint32_t XaddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
xadd res, ecx
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t XaddWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
mov res, ax
xadd res, cx
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t XaddByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
mov res, al
xadd res, cl
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationXadd)
{
DoTestFunctionDWord(&XaddDWord);
DoTestFunctionWord(&XaddWord);
DoTestFunctionByte(&XaddByte);
}
uint32_t XchgDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
xchg eax, ecx
mov res, eax
cmp eax, param1
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t XchgWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
xchg ax, cx
mov res, ax
cmp ax, param1
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t XchgByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
xchg al, cl
mov res, al
cmp al, param1
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationXchg)
{
DoTestFunctionDWord(&XchgDWord);
DoTestFunctionWord(&XchgWord);
DoTestFunctionByte(&XchgByte);
}
uint32_t IncDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
inc eax
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t IncWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
inc ax
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t IncByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
inc al
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationInc)
{
DoTestFunctionDWord(&IncDWord);
DoTestFunctionWord(&IncWord);
DoTestFunctionByte(&IncByte);
}
uint32_t DecDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
dec eax
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t DecWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
dec ax
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t DecByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
dec al
mov res, al
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationDec)
{
DoTestFunctionDWord(&DecDWord);
DoTestFunctionWord(&DecWord);
DoTestFunctionByte(&DecByte);
}
uint32_t MulDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
push edx
mov eax, param1
mov ecx, param2
mul ecx
pushfd
add eax, edx
mov res, eax
pop eax
and eax, ~(fl_S | fl_Z | fl_A | fl_P)
mov ecx, flags
mov [ecx], eax
pop edx
pop ecx
pop eax
}
return res;
}
uint16_t MulWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
push edx
mov ax, param1
mul param2
pushfd
add ax, dx
mov res, ax
pop eax
and eax, ~(fl_S | fl_Z | fl_A | fl_P)
mov ecx, flags
mov [ecx], eax
pop edx
pop ecx
pop eax
}
return res;
}
uint8_t MulByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
mul cl
pushfd
add al, ah
mov res, al
pop eax
and eax, ~(fl_S | fl_Z | fl_A | fl_P)
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationMul)
{
DoTestFunctionDWord(&MulDWord);
DoTestFunctionWord(&MulWord);
DoTestFunctionByte(&MulByte);
}
uint32_t ImulDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
push edx
mov eax, param1
mov ecx, param2
imul ecx
pushfd
add eax, edx
mov res, eax
pop eax
and eax, ~(fl_S | fl_Z | fl_A | fl_P)
mov ecx, flags
mov [ecx], eax
pop edx
pop ecx
pop eax
}
return res;
}
uint16_t ImulWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
push edx
mov ax, param1
imul param2
pushfd
add ax, dx
mov res, ax
pop eax
and eax, ~(fl_S | fl_Z | fl_A | fl_P)
mov ecx, flags
mov [ecx], eax
pop edx
pop ecx
pop eax
}
return res;
}
uint8_t ImulByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
imul cl
pushfd
add al, ah
mov res, al
pop eax
and eax, ~(fl_S | fl_Z | fl_A | fl_P)
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationImul)
{
DoTestFunctionDWord(&ImulDWord);
DoTestFunctionWord(&ImulWord);
DoTestFunctionByte(&ImulByte);
}
uint32_t BtDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
bt eax, cl
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
bt ax, cl
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t BtMemDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
and ecx, 0x1f
bt param1, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtMemWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
and ecx, 0x0f
bt param1, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t BtValDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
and ecx, 0x1f
bt param1, 0x18
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtValWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
and ecx, 0x0f
bt param1, 8
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationBt)
{
DoTestFunctionDWord(&BtDWord);
DoTestFunctionWord(&BtWord);
DoTestFunctionDWord(&BtMemDWord);
DoTestFunctionWord(&BtMemWord);
DoTestFunctionDWord(&BtValDWord);
DoTestFunctionWord(&BtValWord);
}
uint32_t BtsDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
bts eax, cl
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtsWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
bts ax, cl
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t BtsMemDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
and ecx, 0x1f
bts param1, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtsMemWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
and ecx, 0x0f
bts param1, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationBts)
{
DoTestFunctionDWord(&BtsDWord);
DoTestFunctionWord(&BtsWord);
DoTestFunctionDWord(&BtsMemDWord);
DoTestFunctionWord(&BtsMemWord);
}
uint32_t BtrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
btr eax, cl
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtrWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
btr ax, cl
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationBtr)
{
DoTestFunctionDWord(&BtrDWord);
DoTestFunctionWord(&BtrWord);
}
uint32_t BtcDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
btc eax, cl
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t BtcWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
btc ax, cl
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationBtc)
{
DoTestFunctionDWord(&BtcDWord);
DoTestFunctionWord(&BtcWord);
}
uint32_t CmovDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
cmp al, cl
cmovc eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t CmovWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
cmp al, cl
cmovna ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationCmov)
{
DoTestFunctionDWord(&CmovDWord);
DoTestFunctionWord(&CmovWord);
}
uint32_t LockAddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
lock add res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint16_t LockAddWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
mov ax, param1
mov cx, param2
mov res, ax
lock add res, cx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t LockAddByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
mov res, al
lock add res, cl
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LockSubDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
lock sub res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LockXorDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
lock xor res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LockAndDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
lock and res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LockOrDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
lock or res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LockXchgDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
cmp eax, ecx
lock xchg res, ecx
mov res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LockXaddDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
mov res, eax
lock xadd res, ecx
xor res, ecx
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationLock)
{
DoTestFunctionDWord(&LockAddDWord);
DoTestFunctionWord(&LockAddWord);
DoTestFunctionByte(&LockAddByte);
DoTestFunctionDWord(&LockAndDWord);
DoTestFunctionDWord(&LockSubDWord);
DoTestFunctionDWord(&LockXorDWord);
DoTestFunctionDWord(&LockOrDWord);
DoTestFunctionDWord(&LockXchgDWord);
DoTestFunctionDWord(&LockXaddDWord);
}
uint32_t CbxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
cbw
movzx ecx, ax
mov eax, param2
cwd
add eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t MovzxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
lea ecx, param1
movzx eax, byte ptr [ecx + 1]
movzx ecx, word ptr [ecx + 2]
add eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t MovsxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
movsx ecx, cl
movsx eax, ax
add eax, ecx
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t LahfByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov al, param1
mov cl, param2
cmp al, cl
lahf
mov res, ah
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t SahfByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov ah, param1
sahf
mov res, ah
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t StcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
xor eax, eax
stc
setc res
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t ClcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov eax, -1
inc eax
clc
setc res
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t CmcByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
_asm {
push eax
push ecx
mov eax, -1
inc eax
cmc
setc res
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint8_t XlatByte(uint8_t param1, uint8_t param2, uint32_t *flags)
{
uint8_t res;
uint8_t xlat_table[0x100];
for (size_t i = 0; i < 0x100; i++)
xlat_table[(uint8_t)i] = 0x100 - (uint8_t)i;
_asm {
push eax
push ecx
lea ebx, xlat_table
mov al, param1
xlat
add al, param2
xlat
mov res, al
pushfd
pop eax
mov ecx, flags
mov[ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t BswapDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
bswap eax
mov res, eax
add eax, param2
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LeaDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
lea eax, [ecx+eax*4+0x10000]
mov res, eax
xor eax, param2
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t ESPDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push eax
push ecx
mov eax, param1
mov [esp+4], eax
cmp eax, [esp+4]
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
pop eax
}
return res;
}
uint16_t SegWord(uint16_t param1, uint16_t param2, uint32_t *flags)
{
uint16_t res;
_asm {
push eax
push ecx
push ss
pop eax
mov cx, ds
cmp ax, cx
mov res, ax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LodsDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
push edi
lea esi, param1
lodsd
mov res, eax
mov ecx, flags
mov [ecx], esi
pop edi
pop ecx
pop eax
}
return res;
}
uint32_t RepStosDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
push edi
mov eax, param1
mov ecx, 4
lea edi, res
rep stosb
mov eax, ecx
mov ecx, flags
mov [ecx], eax
pop edi
pop ecx
pop eax
}
return res;
}
uint32_t LdsDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
uint8_t mem[6];
_asm {
push eax
push ecx
mov eax, param1
lea ecx, mem
mov [ecx], eax
mov ax, ds
mov [ecx+4], ax
lds eax, mem
mov res, ecx
cmp eax, ecx
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t PopESPDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
push edi
mov edi, esp
mov eax, param1
mov ecx, param2
push 0
push 0
xchg [esp], eax
pop dword ptr [esp]
pop eax
sub edi, esp
mov res, eax
mov ecx, flags
mov [ecx], edi
pop edi
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationOther)
{
DoTestFunctionDWord(&CbxDWord);
DoTestFunctionDWord(&MovzxDWord);
DoTestFunctionDWord(&MovsxDWord);
DoTestFunctionByte(&LahfByte);
DoTestFunctionByte(&SahfByte);
DoTestFunctionByte(&StcByte);
DoTestFunctionByte(&ClcByte);
DoTestFunctionByte(&CmcByte);
DoTestFunctionDWord(&BswapDWord);
DoTestFunctionDWord(&LeaDWord);
DoTestFunctionDWord(&ESPDWord);
DoTestFunctionWord(&SegWord);
DoTestFunctionDWord(&LodsDWord);
DoTestFunctionDWord(&RepStosDWord);
DoTestFunctionDWord(&LdsDWord);
DoTestFunctionDWord(&PopESPDWord);
DoTestFunctionByte(&XlatByte);
}
uint32_t WriteStackDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
push edi
mov edi, esp
push ecx
mov [edi-4], eax
mov eax, [edi-4]
mov esp, edi
mov res, eax
mov ecx, flags
mov [ecx], edi
pop edi
pop ecx
pop eax
}
return res;
}
uint32_t ReadStackDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
push edi
mov edi, esp
push ecx
mov eax, [edi-4]
mov esp, edi
mov res, eax
mov ecx, flags
mov [ecx], edi
pop edi
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationStack)
{
DoTestFunctionDWord(&ReadStackDWord);
DoTestFunctionDWord(&WriteStackDWord);
}
uint32_t JxxDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
cmp eax, param2
jnl label_0
not eax
label_0:
test eax, 1
jnz label_1
add eax, param2
jc label_2
or al, 1
jmp label_0
label_2:
rol eax, 1
label_1:
mov res, eax
pushfd
pop eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LoopDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
movzx ecx, cl
jecxz label_1
label_0:
add eax, eax
loop label_0
label_1:
mov res, eax
mov eax, ecx
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LoopeDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
movzx ecx, cl
jecxz label_1
label_0:
add eax, eax
test ah, 1
loope label_0
label_1:
mov res, eax
mov eax, ecx
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t LoopneDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
mov eax, param1
mov ecx, param2
movzx ecx, cl
jecxz label_1
label_0:
add eax, eax
test ah, 1
loopne label_0
label_1:
mov res, eax
mov eax, ecx
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
uint32_t RetDWord(uint32_t param1, uint32_t param2, uint32_t *flags)
{
uint32_t res;
_asm {
push eax
push ecx
push cs
mov eax, offset(label_1)
push eax
retf
label_1:
mov eax, param1
mov res, eax
mov ecx, flags
mov [ecx], eax
pop ecx
pop eax
}
return res;
}
TEST(IntelTest, VirtualizationBranches)
{
DoTestFunctionDWord(&JxxDWord);
DoTestFunctionDWord(&LoopDWord);
DoTestFunctionDWord(&LoopeDWord);
DoTestFunctionDWord(&LoopneDWord);
DoTestFunctionDWord(&RetDWord);
DoTestFunctionDWord(&CmovDWord);
}
#endif //_WIN64
#endif //_WIN32