#include #include #include enum { THREAD_SIM, THREAD_MONITOR, THREAD_NUM }; HANDLE threads[THREAD_NUM]; int threads_params[THREAD_NUM]; SYSTEM_INFO sys_info; DWORD WINAPI thread_sim(LPVOID param); DWORD WINAPI thread_monitor(LPVOID param); #define SIMOP_EXIT 0x00 #define SIMOP_RESERVE 0x01 #define SIMOP_PASS_BLOCK 0x02 #define SIMOP_NON_SAVE 0x03 #define SIMOP_FREE_REG 0x04 #define SIMOP_RETURN_BLOCK 0x05 #define SIMOP_LOCK_BLOCK 0x06 #define SIMOP_UNLOCK_BLOCK 0x07 #define SIMOP_MESS_REGION 0x08 #define SLEEP_MILLIS 2000 // Некоторые поля увелчены для выравнивания struct sim_cmd{ uint64_t millis_offset; uint64_t op; uint64_t region; uint64_t reg_sz; uint64_t access; }; int main() { int ret = 0; GetSystemInfo(&sys_info); threads[THREAD_SIM] = CreateThread(NULL, 0, thread_sim, &threads_params[THREAD_SIM], 0, NULL); if (!threads[THREAD_SIM]) { printf("Couldn't create simulator\n"); return EXIT_FAILURE; } threads[THREAD_MONITOR] = CreateThread(NULL, 0, thread_monitor, &threads_params[THREAD_MONITOR], 0, NULL); if (!threads[THREAD_MONITOR]) { printf("Couldn't create monitor\n"); ret = EXIT_FAILURE; goto close_sim_thread; } printf("waiting...\n"); DWORD status = WaitForMultipleObjects(THREAD_NUM, threads, TRUE, INFINITE); printf("done waiting (%lu).\n", GetLastError()); close_monitor_thread: CloseHandle(&threads[THREAD_MONITOR]); close_sim_thread: CloseHandle(&threads[THREAD_SIM]); return ret; } int read_sim_cmd(FILE *src, struct sim_cmd *dest) { const size_t cmd_sz = sizeof(struct sim_cmd); size_t bytes_read = fread(dest, sizeof(char), cmd_sz, src); if (bytes_read != cmd_sz) return -ENODATA; return 0; } int write_sim_cmd(FILE *src, struct sim_cmd *dest) { const size_t cmd_sz = sizeof(struct sim_cmd); size_t bytes_written = fwrite(dest, sizeof(char), cmd_sz, src); if (bytes_written != cmd_sz) return -ENODATA; return 0; } #define QUIT_NUMBER 'q' static uint64_t last_clock = 0; static int do_cmd(struct sim_cmd *cmd) { if (cmd->millis_offset > last_clock) Sleep(cmd->millis_offset - last_clock); switch (cmd->op) { case SIMOP_RESERVE: if (!VirtualAlloc((LPVOID)cmd->region, cmd->reg_sz, MEM_RESERVE | MEM_COMMIT, cmd->access)) { return -ENOMEM; } break; case SIMOP_FREE_REG: if (VirtualFree((LPVOID)cmd->region, cmd->reg_sz, MEM_DECOMMIT) == 0) { return -EFAULT; } break; case SIMOP_LOCK_BLOCK: if (VirtualLock((LPVOID)cmd->region, cmd->reg_sz) == 0) { return -ENOLCK; } break; case SIMOP_UNLOCK_BLOCK: if(VirtualUnlock((LPVOID)cmd->region, cmd->reg_sz) == 0) { return -ENOLCK; } break; case SIMOP_PASS_BLOCK: if (!VirtualAlloc((LPVOID)cmd->region, cmd->reg_sz, MEM_COMMIT, cmd->access)) { return -ENOMEM; } break; case SIMOP_NON_SAVE: if (!VirtualAlloc((LPVOID)cmd->region, cmd->reg_sz, MEM_RESERVE | MEM_RESET, cmd->access)) { return -ENOMEM; } case SIMOP_RETURN_BLOCK: if (!VirtualFree((LPVOID)cmd->region, 0, MEM_RELEASE)) { printf("error was %lu\n", GetLastError()); return -EFAULT; } break; case SIMOP_MESS_REGION: printf("messing with pages...\n"); if (cmd->access == PAGE_READWRITE || cmd->access == PAGE_EXECUTE_READWRITE) { printf("memsetting\n"); memset((LPVOID)cmd->region, 0x77, cmd->reg_sz); } else if (cmd->access == PAGE_READONLY) { #define BUFF_SIZE 256 printf("reading to buffer...\n"); char buff[BUFF_SIZE] = {0}; for (size_t i = 0; i < cmd->reg_sz; i += BUFF_SIZE) { memcpy(buff, &((char*)(cmd->region))[i], BUFF_SIZE); } } break; case SIMOP_EXIT: return QUIT_NUMBER; default: break; } return 0; } DWORD WINAPI thread_sim(LPVOID param) { DWORD status = 0; FILE *program = fopen("vm.bin", "r"); if (!program) { printf("can't open file vm.bin\n"); status = EFAULT; goto exit; } static struct sim_cmd cmd; while(read_sim_cmd(program, &cmd) == 0) { int ret = do_cmd(&cmd); printf("command (%02llx) done with code (%d)\n", cmd.op, ret); status = abs(ret); if (ret < 0) { break; } else if (ret == QUIT_NUMBER) { status = 0; break; } } close_program: fclose(program); exit: printf("return from vm\n"); return status; } int write_report(FILE *f) { MEMORYSTATUS ms; GlobalMemoryStatus(&ms); size_t bytes_written = fprintf( f, "Memory status (Total/Avail):\n" "Physical: %zu/%zu\n" "Virtual: %zu/%zu\n" "Page file: %zu/%zu\n" "Page size (bytes): %lu\n" "Granularity: %lu\n\n", ms.dwTotalPhys, ms.dwAvailPhys, ms.dwTotalVirtual, ms.dwAvailVirtual, ms.dwTotalPageFile, ms.dwAvailPageFile, sys_info.dwPageSize, sys_info.dwAllocationGranularity ); if (bytes_written < 1) { return -EFAULT; } return 0; } DWORD WINAPI thread_monitor(LPVOID param) { DWORD status = 0; FILE *report = fopen("report.txt", "w"); if (!report) { printf("fault\n"); status = EFAULT; goto close_report; } for (size_t i = 0; i < 5; i++) { Sleep(SLEEP_MILLIS); printf("report written with status: %d\n", write_report(report)); } close_report: fclose(report); return status; }