📄 system.c
字号:
// System.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "Plugin.h"#include "Buffers.h"#include "System.h"#ifndef __GNUC__#include <crtdbg.h>#endif /* __GNUC__ */#include <objbase.h>// Parse Section Type #define PST_PROC 0#define PST_PARAMS 1#define PST_RETURN 2#define PST_OPTIONS 3#define PCD_NONE 0#define PCD_PROC 1#define PCD_PARAMS 2#define PCD_DONE 3 // Just Continueconst int ParamSizeByType[7] = {0, // PAT_VOID (Size will be equal to 1) 1, // PAT_INT 2, // PAT_LONG 1, // PAT_STRING 1, // PAT_WSTRING 1, // PAT_GUID 0}; // PAT_CALLBACK (Size will be equal to 1)int z1, z2; // I've made them static for easier use at callback procsint LastStackPlace;int LastStackReal;DWORD LastError;volatile SystemProc *LastProc;int CallbackIndex;HINSTANCE g_hInstance;// Return to callback caller with stack restorechar retexpr[4];HANDLE retaddr;#ifndef __GNUC__/*FIXME:GCC cannot compile the inline assembly used by System::Call andSystem::Get, so those functions and their supporting functionsare disabled when using GCC.*/char *GetResultStr(SystemProc *proc){ char *buf = AllocString(); if (proc->ProcResult == PR_OK) lstrcpy(buf, "ok"); else if (proc->ProcResult == PR_ERROR) lstrcpy(buf, "error"); else if (proc->ProcResult == PR_CALLBACK) wsprintf(buf, "callback%d", proc->CallbackIndex); return buf;}#ifdef SYSTEM_LOG_DEBUG// System log debuggin turned on#define SYSTEM_EVENT(a) { _asm { mov logespsave, esp }; LogEvent(a); }#define SYSTEM_LOG_ADD(a) { lstrcat(syslogbuf, a); }#define SYSTEM_LOG_POST { lstrcat(syslogbuf, "\n"); WriteToLog(syslogbuf); *syslogbuf = 0; }HANDLE logfile = NULL;char syslogbuf[4096] = "";int logop = 0, logespsave;void WriteToLog(char *buffer){ DWORD written; char timebuffer[128]; GetTickCount(); if (logfile == NULL) return; SetFilePointer(logfile, 0, 0, FILE_END); wsprintf(timebuffer, "%04d %04d.%03d ", (++logop)%10000, (GetTickCount() / 1000) % 10000, GetTickCount() % 1000); _RPT0(_CRT_WARN, timebuffer); _RPT0(_CRT_WARN, buffer); WriteFile(logfile, timebuffer, lstrlen(timebuffer), &written, NULL); WriteFile(logfile, buffer, lstrlen(buffer), &written, NULL);// FlushFileBuffers(logfile);}void LogEvent(char *a){ char buffer[1024]; wsprintf(buffer, "%s ESP = 0x%08X Stack = 0x%08X Real = 0x%08X", a, logespsave, LastStackPlace, LastStackReal); SYSTEM_LOG_ADD(buffer);}PLUGINFUNCTION(Debug){ char *o1; o1 = popstring(); if (logfile == NULL) if (lstrlen(o1) > 0) { SYSTEMTIME t; char buffer[1024], buftime[1024], bufdate[1024]; // Init debugging logfile = CreateFile(o1, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); SetFilePointer(logfile, 0, 0, FILE_END); logop = 0; GetLocalTime(&t); GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &t, NULL, buftime, 1024); GetDateFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &t, NULL, bufdate, 1024); wsprintf(buffer, "System, %s %s [build "__TIME__" "__DATE__"]\n", buftime, bufdate); WriteToLog(buffer); } else ; else if (lstrlen(o1) > 0) { // Log in to log file WriteToLog(o1); } else { // Stop debugging WriteToLog("Debug stopped.\n\n\n"); CloseHandle(logfile); logfile = NULL; }} PLUGINFUNCTIONEND#else// System log debugging turned off#define SYSTEM_EVENT(a)#define SYSTEM_LOG_ADD(a)#define SYSTEM_LOG_POST#endifPLUGINFUNCTION(Get){ SystemProc *proc = PrepareProc(FALSE); if (proc == NULL) { pushstring("error"); return; } SYSTEM_LOG_ADD("Get "); SYSTEM_LOG_ADD(proc->DllName); SYSTEM_LOG_ADD("::"); SYSTEM_LOG_ADD(proc->ProcName); SYSTEM_LOG_ADD("\n"); SYSTEM_LOG_POST; if ((proc->Options & POPT_ALWRETURN) != 0) { // Always return flag set -> return separate proc and result pushint((int) proc); GlobalFree(pushstring(GetResultStr(proc))); } else { if (proc->ProcResult != PR_OK) { // No always return flag and error result - return result GlobalFree(pushstring(GetResultStr(proc))); // If proc is permanent? if ((proc->Options & POPT_PERMANENT) == 0) GlobalFree((HANDLE) proc); // No, free it } else // Ok result, return proc pushint((int) proc); }} PLUGINFUNCTIONENDPLUGINFUNCTION(Call){ // Prepare input SystemProc *proc = PrepareProc(TRUE); if (proc == NULL) return; SYSTEM_LOG_ADD("Call "); SYSTEM_LOG_ADD(proc->DllName); SYSTEM_LOG_ADD("::"); SYSTEM_LOG_ADD(proc->ProcName); SYSTEM_LOG_ADD("\n"); if (proc->ProcResult != PR_CALLBACK) ParamAllocate(proc); ParamsIn(proc); // Make the call if (proc->ProcResult != PR_ERROR) { switch (proc->ProcType) { case PT_NOTHING: if (proc->ProcResult == PR_CALLBACK) proc = CallBack(proc); break; case PT_PROC: case PT_VTABLEPROC: proc = CallProc(proc); break; case PT_STRUCT: CallStruct(proc); break; } } // Process output if ((proc->Options & POPT_ALWRETURN) != 0) { // Always return flag set - return separate return and result ParamsOut(proc); GlobalFree(pushstring(GetResultStr(proc))); } else { if (proc->ProcResult != PR_OK) { ProcParameter pp; // Save old return param pp = proc->Params[0]; // Return result instead of return value proc->Params[0].Value = (int) GetResultStr(proc); proc->Params[0].Type = PAT_STRING; // Return all params ParamsOut(proc); // Restore old return param proc->Params[0] = pp; } else ParamsOut(proc); } if (proc->ProcResult != PR_CALLBACK) { // Deallocate params if not callback ParamsDeAllocate(proc); // if not callback - check for unload library option if ((proc->Options & POPT_UNLOAD) && (proc->ProcType == PT_PROC) && (proc->Dll != NULL)) FreeLibrary(proc->Dll); // and unload it :) // In case of POPT_ERROR - first pop will be proc error if ((proc->Options & POPT_ERROR) != 0) pushint(LastError); } // If proc is permanent? if ((proc->Options & POPT_PERMANENT) == 0) GlobalFree((HANDLE) proc); // No, free it} PLUGINFUNCTIONEND#endif /* __GNUC__ */PLUGINFUNCTIONSHORT(Int64Op){ __int64 i1, i2 = 0, i3, i4; char *op, *o1, *o2; char buf[128]; // Get strings o1 = popstring(); op = popstring(); i1 = myatoi(o1); // convert first arg to int64 if ((*op != '~') && (*op != '!')) { // get second arg, convert it, free it o2 = popstring(); i2 = myatoi(o2); GlobalFree(o2); } // operation switch (*op) { case '+': i1 += i2; break; case '-': i1 -= i2; break; case '*': i1 *= i2; break; case '/': case '%': // It's unclear, but in this case compiler will use DivMod rountine // instead of two separate Div and Mod rountines. if (i2 == 0) { i3 = 0; i4 = i1; } else {i3 = i1 / i2; i4 = i1 % i2; } if (*op == '/') i1 = i3; else i1 = i4; break; case '|': if (op[1] == '|') i1 = i1 || i2; else i1 |= i2; break; case '&': if (op[1] == '&') i1 = i1 && i2; else i1 &= i2; break; case '^': i1 ^= i2; break; case '~': i1 = ~i1; break; case '!': i1 = !i1; break; case '<': if (op[1] == '<') i1 = i1 << i2; else i1 = i1 < i2; break; case '>': if (op[1] == '>') i1 = i1 >> i2; else i1 = i1 > i2; break; case '=': i1 = (i1 == i2); break; } // Output and freedom myitoa64(i1, buf); pushstring(buf); GlobalFree(o1); GlobalFree(op);} PLUGINFUNCTIONEND__int64 GetIntFromString(char **p){ char buffer[128], *b = buffer; (*p)++; // First character should be skipped while (((**p >= 'a') && (**p <= 'f')) || ((**p >= 'A') && (**p <= 'F')) || ((**p >= '0') && (**p <= '9')) || (**p == 'X') || (**p == '-') || (**p == 'x') || (**p == '|')) *(b++) = *((*p)++); *b = 0; (*p)--; // We should point at last digit return myatoi(buffer);}#ifndef __GNUC__SystemProc *PrepareProc(BOOL NeedForCall){ int SectionType = PST_PROC, // First section is always proc spec ProcType = PT_NOTHING, // Default proc spec ChangesDone = 0, ParamIndex = 0, temp = 0, temp2, temp3, temp4; BOOL param_defined = FALSE; SystemProc *proc = NULL; char *ibuf, *ib, *sbuf, *cbuf, *cb; // Retrieve proc specs cb = (cbuf = AllocString()); // Current String buffer sbuf = AllocString(); // Safe String buffer ib = ibuf = popstring(); // Input string // Parse the string while (SectionType != -1) { // Check for Section Change BOOL changed = TRUE; ChangesDone = SectionType; if (SectionType != PST_PROC && proc == NULL) // no proc after PST_PROC is done means something is wrong with // the call syntax and we'll get a crash because everything needs // proc from here on. break; switch (*ib) { case 0x0: SectionType = -1; break; case '#': SectionType = PST_PROC; ProcType = PT_NOTHING; break; case '(': SectionType = PST_PARAMS; // fake-real parameter: for COM interfaces first param is Interface Pointer ParamIndex = ((ProcType == PT_VTABLEPROC)?(2):(1)); temp3 = temp = 0; param_defined = FALSE; break; case ')': SectionType = PST_RETURN; temp3 = temp = 0; break; case '?': SectionType = PST_OPTIONS; temp = 1; break; default: changed = FALSE; } // Check for changes if (changed) { switch (ChangesDone) { case PST_PROC: *cb = 0; // Adopt proc if (proc == NULL) { proc = (SystemProc *) GlobalAlloc(GPTR, sizeof(SystemProc)); proc->Options = 0; proc->ParamCount = 0; } // Default parameters *proc->DllName = 0; *proc->ProcName = 0; proc->Dll = NULL; proc->Proc = NULL; proc->ProcType = ProcType; proc->ProcResult = PR_OK; // Section changed and previos section was Proc switch (ProcType) { case PT_NOTHING: // Is it previous proc or just unknown proc? if (cb != cbuf) { // Previous proc (for clear up) SystemProc *pr = NULL; if (proc != NULL) GlobalFree(proc); // Get already defined proc proc = (SystemProc *) myatoi(cbuf); if (!proc) break; // Find the last clone at proc queue while (proc && (proc->Clone != NULL)) proc = (pr = proc)->Clone; // Clear parents record for child callback proc if (pr != NULL) pr->Clone = NULL; // Never Redefine? if ((proc->Options & POPT_NEVERREDEF) != 0) { // Create new proc as copy proc = GlobalCopy(proc); // NeverRedef options is never inherited proc->Options &= (~POPT_NEVERREDEF) & (~POPT_PERMANENT); } else proc->Options |= POPT_PERMANENT; // Proc is old -> permanent } break; case PT_PROC: case PT_VTABLEPROC: lstrcpy(proc->DllName, sbuf); case PT_STRUCT: lstrcpy(proc->ProcName, cbuf); break; } break; case PST_PARAMS: if (param_defined) proc->ParamCount = ParamIndex; else // not simply zero because of vtable calls proc->ParamCount = ParamIndex - 1; case PST_RETURN: case PST_OPTIONS: break; } ib++; cb = cbuf; continue; } // Parse the section ChangesDone = PCD_NONE; switch (SectionType) { // Proc sections parser case PST_PROC: switch (*ib) { case ':': case '-': // Is it '::' if ((*(ib) == '-') && (*(ib+1) == '>')) { ProcType = PT_VTABLEPROC; } else { if ((*(ib+1) != ':') || (*(ib) == '-')) break; ProcType = PT_PROC; } ib++; // Skip next ':' if (cb > cbuf) { *cb = 0; lstrcpy(sbuf, cbuf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -