4494 lines
87 KiB
C++
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
|