#include        "defs.h"


VOID    FuckUpStack(){
        ULONG_PTR       stackTop;
        ULONG_PTR       currentStack;
        ULONG           index;
        PULONG          pfuckup;
        
        stackTop = __readfsdword(0x4);
        currentStack = (ULONG_PTR)_AddressOfReturnAddress();
        
        currentStack -= 0x100;
        
        pfuckup = (PULONG)currentStack;
        
        for (index = 0; index < (stackTop - currentStack)/sizeof(ULONG); index++)
                pfuckup[index] = 0xDEADC0DE;    
        
        __asm rdtsc
        __asm and eax, 0FCh
        __asm sub esp, eax
        __asm popad 
        __asm ret                 
}

VOID    CheckCheckSum(){
        ULONG_PTR               imagebase;
        DWORD                   dwRead;
        UCHAR                   md5_sum[0x10];
        HCRYPTPROV              hProv;
        HCRYPTHASH              hHashMd5;
        DWORD                   hash_data_len;
        PIMAGE_DOS_HEADER       pmz;
        PPEHEADER32             pe32;
        PSECTION_HEADER         section;
        
        imagebase            = __readfsdword(0x30);
        imagebase            = *(PULONG_PTR)(imagebase + 8);
        
        pmz = (PIMAGE_DOS_HEADER)imagebase;
        pe32= (PPEHEADER32)(imagebase + pmz->e_lfanew);
        section = (PSECTION_HEADER)((ULONG_PTR)pe32 + 4 + sizeof(IMAGE_FILE_HEADER) + pe32->pe_sizeofoptionalheader);
        
        CryptAcquireContextW(&hProv, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
        CryptCreateHash(hProv, CALG_MD5,  0, 0, &hHashMd5);
        CryptHashData(hHashMd5, (const BYTE *)(imagebase + section[0].sh_virtualaddress), section[0].sh_sizeofrawdata, 0);
        hash_data_len = 0x10;
        CryptGetHashParam(hHashMd5, HP_HASHVAL, (BYTE *)&md5_sum, &hash_data_len, 0);
        CryptDestroyHash(hHashMd5);
        CryptReleaseContext(hProv, 0);
        
        if (memcmp((void *)(imagebase + 0x40), md5_sum, 0x10))
                FuckUpStack();
        
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
        HBITMAP hbmp; 
        BITMAP  bm;
        PAINTSTRUCT ps;
        HDC         hdcMem, hdc;
        RECT        rect;
        HICON       hicon;
        
        switch(msg){
                case WM_CREATE:
                        hicon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(101));
                        CheckCheckSum();
                        SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon);
                        SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
                        break;
                case WM_CLOSE:
                        DestroyWindow(hwnd);
                        break;
                case WM_DESTROY:
                        PostQuitMessage(0);
                        break;
                case WM_PAINT:
                        GetClientRect(hwnd, &rect);
                        hbmp = LoadBitmap(GetModuleHandle(0), MAKEINTRESOURCE(102));
                        hdc = BeginPaint(hwnd, &ps);
                        
                        hdcMem = CreateCompatibleDC(NULL);
                        SelectObject(hdcMem, hbmp);
                        CheckCheckSum();
                        GetObject(hbmp, sizeof(bm), &bm);
                        
                        StretchBlt(hdc, 0,0, rect.right, rect.bottom, hdcMem, 0,0, bm.bmWidth, bm.bmHeight, SRCCOPY); 
                        
                        DeleteDC(hdcMem);
                        DeleteObject(hbmp);
                        EndPaint(hwnd, &ps);
                        break; 
                case WM_SIZE:
                        GetClientRect(hwnd, &rect);
                        CheckCheckSum();
                        InvalidateRect(hwnd, &rect, FALSE);
                        break;
                case WM_TIMER:
                        if (wParam == 1010)
                                MessageBox(hwnd, L"This is trial program, please register...", L"trial", 0);
                        CheckCheckSum();
                        break;
                default:
                        return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
}

int     __cdecl wmain(int argc, wchar_t **argv){
WNDCLASSEX      wc;
        MSG             Msg;
        HANDLE          hwnd;
        
        memset(&wc, 0, sizeof(WNDCLASSEX));
        wc.cbSize        = sizeof(WNDCLASSEX);
        wc.style         = 0;
        wc.lpfnWndProc   = WndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = GetModuleHandle(0);
        wc.hIcon         = LoadIcon(NULL, MAKEINTRESOURCE(101));
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wc.lpszMenuName  = NULL;
        wc.lpszClassName = L"TestAppForChecksum";
        wc.hIconSm       = LoadIcon(NULL, MAKEINTRESOURCE(101));        
        
        RegisterClassEx(&wc);

        hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
                              L"TestAppForChecksum",
                              L"TestApp",
                              WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
                              NULL, NULL, GetModuleHandleA(0), NULL);

        ShowWindow(hwnd, SW_SHOW);
        UpdateWindow(hwnd);
        
        SetTimer(hwnd, 1010, 10000, NULL);
        SetTimer(hwnd, 0101, 3000, NULL);
        while(GetMessage(&Msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
     
        return 1;
        
}
