Czy kod po włączeniu może wytworzyć inny kod maszynowy i ...

0

Czy kod po włączeniu może wytworzyć inny kod maszynowy i włączyć go w osobnym wątku ?

0

Tak.

0

Oczywiscie.

  1. Co tylko zechcesz
  2. CreateThread()
0

Jak się tendencja utrzyma (jedno zdanie więcej niż poprzednik) to w tym wątku coś więcej pojawi się za miesiąc.

Ja jak zwykle z naklepanym w kilkanaście minut przykładem, 'małym', 'użytecznym' i 'poprawnym politycznie'.

#include <windows.h>
#include <iostream>
using namespace std;

// nie wszystkie kompilatory maja tak 'nowoczesne' naglowki zeby miec te flage
#define HEAP_CREATE_ENABLE_EXECUTE 0x00040000 

class ShowMessageBox {
     static class ExecutableHeap {
          HANDLE executableHeap;
     public:
          void* alloc(size_t size) {
               return HeapAlloc(executableHeap, 0, size);
          }
          void  free(void *ptr) {
               HeapFree(executableHeap, 0, ptr);
          }
          ExecutableHeap()
               : executableHeap(HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0)) {}
          
          ~ExecutableHeap() {
               HeapDestroy(executableHeap);
          }
     } executableHeap;
     
#pragma pack(push, 1)
     struct Code {
          BYTE bPushd1;         DWORD dwType;
          BYTE bPushd2;         DWORD dwCaption;
          BYTE bPushd3;         DWORD dwText;
          BYTE bPushd4;         DWORD dwHWND;
          BYTE bCallOff;        DWORD dwAddress;
          BYTE bRetn;           WORD  wRetSize;
     } *code;
#pragma pack(pop)

public:
     ShowMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
          code = (Code*) executableHeap.alloc(sizeof(Code));
          
          code->bPushd1   = code->bPushd2 = code->bPushd3 = code->bPushd4 = 0x68;
          code->bCallOff  = 0xE8;
          code->bRetn     = 0xC2;
          code->wRetSize  = sizeof(DWORD);
          
          code->dwType    = (DWORD)uType;
          code->dwCaption = (DWORD)lpCaption;
          code->dwText    = (DWORD)lpText;
          code->dwHWND    = (DWORD)hWnd;
          
          DWORD ptr;
          ptr = (DWORD) GetProcAddress(LoadLibrary("user32.dll"), "MessageBoxA");
          code->dwAddress = ptr - (DWORD)&code->bRetn;
     }
     
     ~ShowMessageBox() {
          executableHeap.free(code);
     }

     DWORD conquerWorld() {
          HANDLE hThread;
          DWORD  retn;
          
          hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)code, 0, 0, 0);
          WaitForSingleObject(hThread, INFINITE);
          
          GetExitCodeThread(hThread, &retn);
          CloseHandle(hThread);

          return retn;
     }
};

ShowMessageBox::ExecutableHeap ShowMessageBox::executableHeap;
        
int main() {
     clog << "before." << endl;

     ShowMessageBox smb(0, "Małą czarną?", "zue zuo", MB_ICONWARNING | MB_YESNO);
     
     DWORD btn = smb.conquerWorld();
     cout << (btn == IDYES ? "Yes." : btn == IDNO ? "No." : "WTF?") << endl;
     
     clog << "after."  << endl;
}

Buduje? 'Buduje'. Odpala w innym wątku? Odpala. Za ewentualne szkody nie odpowiedam... szkody moralne oczywiście.

Funkcjonuje to tak - na oddzielnej stercie z prawami do wykonywania tworzy blok i składa do kupy stałe + argumenty w jeden spójny kod z zakodowanymi wartościami zmiennych i bezpośrednim wywołaniem MessageBoksa prosto z user32 (takie rzeczy to tylko w runtime...). Struktura Code, a raczej pary jej składowych, to po prostu reprezentacja kolejnych instrukcji kodu maszynowego. conquerWorld() niestety nie robi tego co powinno (brak czasu i umiejętności) a jedynie tworzy nowy wątek ze zbudowanego kodu, czeka na jego zakończenie i zwraca wynik MessageBoksa. Cała filozofia. Jak widać dać się da, da się nawet napisać to w bardzo 'oryginalnym' stylu (zważywszy, że na upartego to samo można w kilku-kilkunastu linijkach zrobić).

A poważnie to dynamiczne budowanie kodu to podstawa JIT używanego powszechnie w maszynach wirtualnych. Oczywiście protectory i inne poważniejsze twory zabezpieczające pliki wykonywalne także często budują kod podczas wykonywania - chociażby takie przekierowanie importów.

Dobra, pobawiłem się to wracam nudzić się dalej.

0

Dzięki wielkie :) .

0

Ja też dziękuję, zawsze chciałem sobie do interpretera JIT dodać, a zacząć było najtrudniej. Mam co psuć, będę sobie psuł. Ciekawe, ile "nieprawidłowych operacji" minie, zanim będzie wszystko działać jak należy ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1