Kann jemand einen Teil diese Sourcecodes erklären?



  • der code ist von dieser website

    https://stackoverflow.com/questions/40325495/how-to-load-registry-hive-for-all-users-in-a-loop

    BOOL g_IsXP;// true if we on winXP, false otherwise
    static volatile UCHAR guz;
    static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
    
    NTSTATUS ImpersonateIfConformToken(HANDLE hToken)
    {
        ULONG cb = 0, rcb = 0x200;
        PVOID stack = alloca(guz);
    
        union {
            PVOID buf;
            PTOKEN_PRIVILEGES ptp;
        };
    
        NTSTATUS status;
        do 
        {
            if (cb < rcb)
            {
                cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
            }
    
            if (0 <= (status = ZwQueryInformationToken(hToken, TokenPrivileges, buf, cb, &rcb)))
            {
                if (ULONG PrivilegeCount = ptp->PrivilegeCount)
                {
                    PLUID_AND_ATTRIBUTES Privileges = ptp->Privileges;
                    do 
                    {
                        if (Privileges->Luid.LowPart == SE_CREATE_TOKEN_PRIVILEGE && !Privileges->Luid.HighPart)
                        {
                            static SECURITY_QUALITY_OF_SERVICE sqos = {
                                sizeof sqos, SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE
                            };
    
                            static OBJECT_ATTRIBUTES soa = { sizeof(soa), 0, 0, 0, 0, &sqos };
    
                            if (0 <= (status = ZwDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, &soa, FALSE, TokenImpersonation, &hToken)))
                            {
                                if (Privileges->Attributes & SE_PRIVILEGE_ENABLED)
                                {
                                    status = STATUS_SUCCESS;
                                }
                                else
                                {
                                    static TOKEN_PRIVILEGES tp = {
                                        1, { { { SE_CREATE_TOKEN_PRIVILEGE }, SE_PRIVILEGE_ENABLED } }
                                    };
    
                                    status = ZwAdjustPrivilegesToken(hToken, FALSE, &tp, 0, 0, 0);
                                }
    
                                if (status == STATUS_SUCCESS)
                                {
                                    status = ZwSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hToken, sizeof(HANDLE));
                                }
    
                                ZwClose(hToken);
                            }
    
                            return status;
                        }
                    } while (Privileges++, --PrivilegeCount);
                }
    
                return STATUS_PRIVILEGE_NOT_HELD;
            }
    
        } while (status == STATUS_BUFFER_TOO_SMALL);
    
        return status;
    }
    
    NTSTATUS GetCreateTokenPrivilege()
    {
        BOOLEAN b;
        RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &b);
    
        ULONG cb = 0, rcb = 0x10000;
        PVOID stack = alloca(guz);
    
        union {
            PVOID buf;
            PBYTE pb;
            PSYSTEM_PROCESS_INFORMATION pspi;
        };
    
        NTSTATUS status;
        do 
        {
            if (cb < rcb)
            {
                cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
            }
    
            if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &rcb)))
            {
                status = STATUS_UNSUCCESSFUL;
    
                ULONG NextEntryOffset = 0;
                do 
                {
                    pb += NextEntryOffset;
    
                    if (pspi->InheritedFromUniqueProcessId && pspi->UniqueProcessId)
                    {
                        CLIENT_ID cid = { pspi->UniqueProcessId };
    
                        NTSTATUS s = STATUS_UNSUCCESSFUL;
                        HANDLE hProcess, hToken;
    
                        if (0 <= ZwOpenProcess(&hProcess, g_IsXP ? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &cid))
                        {
                            if (0 <= ZwOpenProcessToken(hProcess, TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
                            {
                                s = ImpersonateIfConformToken(hToken);
    
                                NtClose(hToken);
                            }
    
                            NtClose(hProcess);
                        }
    
                        if (s == STATUS_SUCCESS)
                        {
                            return STATUS_SUCCESS;
                        }
                    }
    
                } while (NextEntryOffset = pspi->NextEntryOffset);
    
                return status;
            }
    
        } while (status == STATUS_INFO_LENGTH_MISMATCH);
    
        return STATUS_UNSUCCESSFUL;
    }
    

    Ich weiss der Großteil des geposteten Codes ist Winapi, aber die fraglichen Stellen sind in "C", also hoffe ich hier richtig zu sein.

    warum steht da "static volatile UCHAR guz;"
    warum wird in beiden Funktionen "PVOID stack = alloca(guz);" aufgerufen? "gzu" wurde nicht durch das Programm inizialisiert, sondern hat irgendeinen Anfangswert oder übersehe ich da was?
    Den Code habe ich übrigens erfolgreich in mein Programm eingebaut, nur verstehe ich die erwähnte Stelle nicht.

    Wer kann helfen?



  • @einsteiger sagte in Kann jemand einen Teil diese Sourcecodes erklären?:

    warum steht da "static volatile UCHAR guz;"
    warum wird in beiden Funktionen "PVOID stack = alloca(guz);" aufgerufen? "gzu" wurde nicht durch das Programm inizialisiert, sondern hat irgendeinen Anfangswert oder übersehe ich da was?

    Es hat nicht irgendeinen Anfangswert, sondern 0, da es sich um eine Variable mit statischer Lebensdauer handelt. Da wird also jedesmal ein Array der Größe 0 auf dem Stack alloziert, und ein Zeiger darauf zurückgegeben. Eigentlich wird also die aktuelle Stackgrenze (ist das der Framepointer? kA) ermittelt. Wahrscheinlich gibts irgendeine Optimierung, die verhindert, dass das zuverlässig klappt, wenn man einfach alloca(0) schreibt, deshalb wird guz hier volatile deklariert.

    Alles in allem ist das immer noch hochgradig unportabel und hat mit Standard-C relativ wenig zu tun.



  • Danke für die Erklärung. Für was könnte das Ermitteln der Stackgrenze gut sein?



  • Der Stack wird einfach intern als Buffer benutzt um keinen Speicher mit malloc/new zu allozieren.

    Mit dem ersten Aufruf wird der oberste Punkt des freien Stacks benutzt. Jeder Aufruf von alloca holt wieder ein Stück vom Stack, sofern der Speicher eben noch nicht ausreicht. Die Differenz der Zeiger vom letzten alloca Aufruf und dem ersten alloca(0), liefert dann die zur Verfügung stehende Buffergröße.

    Ich finde den Code albern nur um einen malloc/new Aufruf zu sparen...