system.c

来自「NullSofts criptable install system2.28源代」· C语言 代码 · 共 1,412 行 · 第 1/3 页

C
1,412
字号
            push    ebp
            // Save previous stack location
            mov     LastStackReal, esp
        }

        if (LastStackPlace == 0)
        {
            _asm
            {
                // Create new stack
                mov     eax, NEW_STACK_SIZE
                call    _alloca_probe
                mov     LastStackPlace, esp
            }
        } else
            _asm
            {
                // Move stack pointer
                mov     esp, LastStackPlace
            }
    }

    // Push arguments to stack
    for (z1 = proc->ParamCount; z1 > 0; z1--)
    {
        // Long types
        if (proc->Params[z1].Size == 2)
        {
            z2 = proc->Params[z1]._value;
            _asm    push    z2;
        }
        // Default
        z2 = proc->Params[z1].Value;
        _asm    push    z2;
    }

    // Call the proc and save return
    z1 = (int) proc->Proc;

    // Save proc
    proc->Clone = (SystemProc *) LastProc;
    _asm 
    {
        mov eax, proc
        mov LastProc, eax
    }
    //LastProc = proc;

    SYSTEM_EVENT("\n\t\t\tNear call          ")
    SYSTEM_LOG_POST;

    // workaround for bug #1535007
    // http://sf.net/tracker/index.php?func=detail&aid=1535007&group_id=22049&atid=373085
    //
    // If a function returns short and doesn't clear eax in the process,
    // it will only set 2 bytes of eax, and the other 2 bytes remain
    // "random". In this case, they'll be part of the proc pointer.
    //
    // To avoid this, eax is cleared before the function is called. This
    // makes sure the value eax will contain is only what the function
    // actually sets.
    _asm xor eax, eax

    _asm
    {
        // Call
        call    z1
        // Return
        mov     z1, eax
        mov     z2, edx
    }

    SYSTEM_LOG_ADD("Back from ");
    SYSTEM_LOG_ADD(LastProc->ProcName);
    SYSTEM_EVENT("\n\t\t\tShort-After call   ")

    if ((CallbackIndex) && (!(LastProc->Options & POPT_GENSTACK)))
    {
        _asm
        {
            // Restore real stack location
            mov     LastStackPlace, esp
            mov     esp, LastStackReal
            pop     ebp
        }
    }

    // Restore proc
    _asm 
    {
       mov eax, LastProc
       mov proc, eax
    }
//    proc = LastProc;
    LastProc = proc->Clone;

    // In case of cdecl convention we should clear stack
    if ((proc->Options & POPT_CDECL) != 0)
    {
        if ((CallbackIndex > 0) && ((proc->Options & POPT_GENSTACK) == 0))
        {
            // In case of temporary stack
            for (z3 = 1; z3 <= proc->ParamCount; z3++)
                LastStackPlace += 4*proc->Params[z3].Size;
        } else
        {
            // in case of real stack
            for (z3 = 1; z3 <= proc->ParamCount; z3++)
            {   
                if (proc->Params[z3].Size == 2) 
                    _asm    pop    edx;
                _asm    pop    edx;
            }
        }
    }

    // In case of cleared call-proc-queue -> clear allocated stack place (more flexible)
    if (LastProc == NULL) LastStackPlace = (int) NULL;

    // Save return
    proc->Params[0].Value = z1;
//    if (proc->Params[0].Size == 2) 
        proc->Params[0]._value = z2;
    // Proc result: OK
    proc->ProcResult = PR_OK;

    // In case of POPT_ERROR -> GetLastError
    if ((proc->Options & POPT_ERROR) != 0)
    {
        LastError = GetLastError();
    }

    SYSTEM_EVENT("\n\t\t\tAfter call         ")
#ifdef SYSTEM_LOG_DEBUG
    {
        char buf[1024];
        wsprintf(buf, "\n\t\t\tReturn              0x%08X    0x%08X", z1, z2);
        SYSTEM_LOG_ADD(buf);
    }
#endif
    SYSTEM_LOG_POST;

    _asm 
    {
        // Return
        mov     eax, proc
        // Restore registers
        pop     esi
        pop     edi
        pop     ebx
        // Restore stack pointer
        mov     esp, ebp
        pop     ebp
        // Return
        ret
    }
}

SystemProc __declspec(naked) *RealCallBack()
{
    SystemProc *proc;
    
    _asm 
    {
        // Save stack
        push    ebp
        mov     ebp, esp
        // Stack space for local variables
        sub     esp, __LOCAL_SIZE   
        // Save all usable registers to free our hands
        push    ebx
        push    edi
        push    esi

        // Arguments pointer
        mov     z2, esp    // 1-st arg - 4*4 (pushes) - 4 (return) - __LOCAL_SIZE
        add     z2, __LOCAL_SIZE
        add     z2, 5*4
        // Our callback proc
        mov     proc, eax
    }

    SYSTEM_LOG_ADD("Called callback from ");
    SYSTEM_LOG_ADD(LastProc->ProcName);
    SYSTEM_EVENT("\n\t\t\tShort-After call   ")
    SYSTEM_LOG_POST;

    // Find last unused clone
    while ((proc->Clone != NULL)) proc = proc->Clone;
    // 2. Create new clone
    proc = (proc->Clone = GlobalCopy(proc));
    // 3. Set clone option
    proc->Options |= POPT_CLONE;

    // Read arguments
    proc->ArgsSize = 0;
    for (z1 = 1; z1 <= proc->ParamCount; z1++)
    {
        // Default
        proc->Params[z1].Value = *(((int*)z2)++);
        proc->ArgsSize += 4;
        // Long only
        if (proc->Params[z1].Size == 2)
        {
            proc->Params[z1]._value = *(((int*)z2)++);
            proc->ArgsSize += 4;
        }
    }
    proc->ProcResult = PR_CALLBACK;

    _asm
    {
        // Return
        mov     eax, proc

        // Save temporary stack info
        push    ebp
//        push    LastStackPlace
        mov     LastStackPlace, esp
        // Restore real stack
        mov     esp, LastStackReal
        pop     ebp
//        pop     LastStackReal
    }

    _asm
    {
        // Fake return from System::Call

        // Restore registers
        pop     esi
        pop     edi
        pop     ebx
        // Restore stack pointer
        mov     esp, ebp
        pop     ebp
        // Return
        ret
    }
}


SystemProc __declspec(naked) *CallBack(SystemProc *proc)
{
    _asm 
    {
        // Save stack
        push    ebp
        mov     ebp, esp
        // Stack space for local variables
        sub     esp, __LOCAL_SIZE
        // Save all usable registers to free our hands
        push    ebx
        push    edi
        push    esi
    }

  // MessageBox(NULL, "cool1", "Cool", MB_OK);

    SYSTEM_LOG_ADD("\t\tReturn from callback:\n");
    SYSTEM_EVENT("\t\t\tBefore call-back   ");
    SYSTEM_LOG_POST;

    //z1 = proc->Params[0].Value;
    //z2 = proc->Params[0]._value;
    //z1 = &(proc->Params[0].Value);
    _asm
    {
        mov eax, proc
        add eax, SYSTEM_ZERO_PARAM_VALUE_OFFSET
        push [eax]
        push [eax+4]
    }
    
    // Adjust return statement
    if ((proc->Options & POPT_CDECL) == 0) retexpr[1] = proc->ArgsSize;
    else retexpr[1] = 0x0;

    // Right return statement address
    retaddr = (HANDLE) retexpr;

    // Remove unneeded callback proc
    GlobalFree((HANDLE) proc);

//    MessageBox(NULL, "cool2", "Cool", MB_OK);

    _asm
    {
        // Prepare return
        // callback proc result
        pop edx
        pop eax

        // Restore temporary stack and return

        // Save real stack info
        // Save previous stack location
//        push    LastStackReal
        push    ebp
        mov     LastStackReal, esp
        // Move stack pointer
        mov     esp, LastStackPlace
//        pop     LastStackPlace
        pop     ebp        
    }
        
#ifdef SYSTEM_LOG_DEBUG
    _asm
    {
        push eax
        push edx
    }
    SYSTEM_EVENT("\n\t\t\tSh-Before call-back");
    SYSTEM_LOG_POST;        
    _asm
    {
        // callback proc result
        pop edx
        pop eax
    }
#endif

    // Fake return from Callback
    _asm {
        // Restore registers
        pop     esi
        pop     edi
        pop     ebx
        // Restore stack pointer
        mov     esp, ebp
        pop     ebp
        // Return
        jmp     retaddr
    }
}

HANDLE CreateCallback(SystemProc *cbproc)
{
    char *mem;

    if (cbproc->Proc == NULL)
    {
        // Set callback index
        cbproc->CallbackIndex = ++(CallbackIndex);
        cbproc->Options |= POPT_PERMANENT;

        mem = (char *) (cbproc->Proc = VirtualAlloc(NULL, 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE));
        *(mem++) = (char) 0xB8; // Mov eax, const
        *(((int *)mem)++) = (int) cbproc;
        *(mem++) = (char) 0xe9; // Jmp relative
        *((int *)mem) = (int) RealCallBack;
        *((int *)mem) -= ((int) mem) + 4;
    }

    // Return proc address
    return cbproc->Proc;
}

void CallStruct(SystemProc *proc)
{
    BOOL ssflag;
    int i, structsize = 0, size = 0;
    char *st, *ptr;

    SYSTEM_LOG_ADD("\t\tStruct...");

    // Calculate the structure size 
    for (i = 1; i <= proc->ParamCount; i++)
        if (proc->Params[i].Option < 1)
            structsize += proc->Params[i].Size * 4;
        else
            structsize += proc->Params[i].Option-1;
    
    // Struct exists?
    if (proc->Proc == NULL)
        // No. Allocate struct memory
        proc->Proc = (HANDLE) GlobalAlloc(GPTR, structsize);
    else  // In case of zero size defined structure use mapped size 
        if (structsize == 0) structsize = (int) GlobalSize((HANDLE) proc->Proc);
    
    // Pointer to current data
    st = (char*) proc->Proc;

    for (i = 1; i <= proc->ParamCount; i++)
    {
        ssflag = FALSE;

        // Normal or special block?
        if (proc->Params[i].Option < 1)
        {
            // Normal
            size = proc->Params[i].Size*4;
            ptr = (char*) &(proc->Params[i].Value);
        }
        else
        {
            int intmask[4] = {0xFFFFFFFF, 0x000000FF, 0x0000FFFF, 0x00FFFFFF};

            // Special
            size = proc->Params[i].Option-1;

            switch (proc->Params[i].Type)
            {
            case PAT_VOID: ptr = NULL; break;
            case PAT_LONG: 
                // real structure size
                proc->Params[i].Value = structsize;
                proc->Params[i]._value = 0;
                ssflag = TRUE;
            case PAT_INT: 
                // clear unused value bits
                proc->Params[i].Value &= intmask[((size >= 0) && (size < 4))?(size):(0)];
                // pointer
                ptr = (char*) &(proc->Params[i].Value); 
                break;

            case PAT_STRING: 
            case PAT_GUID: 
            case PAT_WSTRING: 
                ptr = (char*) proc->Params[i].Value; break;
            }
        }

        // Process them!
        if (ptr != NULL)
        {
            // Input
            if ((proc->Params[i].Input != IOT_NONE) || (ssflag))
                copymem(st, ptr, size);

            // Output
            if (proc->Params[i].Output != IOT_NONE)
                copymem(ptr, st, size);
        }

        // Skip to next data block
        st += size;
    }

    SYSTEM_LOG_POST;

    // Proc virtual return - pointer to memory struct
    proc->Params[0].Value = (int) proc->Proc;
}

#endif /* __GNUC__ */

BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
        g_hInstance=hInst;
        
        if (ul_reason_for_call == DLL_PROCESS_ATTACH)
        {
            // change the protection of return command
            VirtualProtect(&retexpr, sizeof(retexpr), PAGE_EXECUTE_READWRITE, &LastStackPlace);

            // initialize some variables
            LastStackPlace = 0;
            LastStackReal = 0;
            LastError = 0;
            LastProc = NULL;
            CallbackIndex = 0;
            retexpr[0] = (char) 0xC2;
            retexpr[2] = 0x00;
        }

        return TRUE;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?