2026-06-19 17:51:51 -07:00
|
|
|
#ifdef WITH_GUI
|
|
|
|
|
|
|
|
|
|
#include "ExploitPanel.hpp"
|
|
|
|
|
|
|
|
|
|
#include <wx/wx.h>
|
|
|
|
|
|
2026-06-26 20:55:55 -07:00
|
|
|
#include <thread>
|
|
|
|
|
#include <atomic>
|
|
|
|
|
|
2026-06-19 17:51:51 -07:00
|
|
|
#include "AppFrame.hpp"
|
2026-06-26 17:23:09 -07:00
|
|
|
#include "../m8/run.h"
|
2026-06-19 17:51:51 -07:00
|
|
|
|
2026-06-26 20:55:55 -07:00
|
|
|
static const char* stage_to_string(int stage)
|
|
|
|
|
{
|
|
|
|
|
switch (stage) {
|
|
|
|
|
case STAGE_PREPARE: return "Checking if device is ready";
|
|
|
|
|
case STAGE_RESET: return "Checking if device is ready";
|
|
|
|
|
case STAGE_SETUP: return "Setting up the exploit (this is the heap spray)";
|
|
|
|
|
case STAGE_SPRAY: return "Setting up the exploit (this is the heap spray)";
|
|
|
|
|
case STAGE_PATCH: return "Right before trigger (this is the real bug setup)";
|
|
|
|
|
case STAGE_PONGO: return "Booting...";
|
|
|
|
|
case STAGE_JAILBREAK: return "Booting...";
|
|
|
|
|
case STAGE_DONE: return "Done.";
|
|
|
|
|
default: return "Working...";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int stage_to_progress(int stage)
|
|
|
|
|
{
|
|
|
|
|
switch (stage) {
|
|
|
|
|
case STAGE_PREPARE: return 5;
|
|
|
|
|
case STAGE_RESET: return 15;
|
|
|
|
|
case STAGE_SETUP: return 30;
|
|
|
|
|
case STAGE_SPRAY: return 50;
|
|
|
|
|
case STAGE_PATCH: return 70;
|
|
|
|
|
case STAGE_PONGO: return 90;
|
|
|
|
|
case STAGE_JAILBREAK: return 95;
|
|
|
|
|
case STAGE_DONE: return 100;
|
|
|
|
|
default: return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 17:51:51 -07:00
|
|
|
ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent)
|
|
|
|
|
: DevicePanel(frame, parent)
|
|
|
|
|
{
|
|
|
|
|
auto* root = new wxBoxSizer(wxVERTICAL);
|
2026-06-26 20:55:55 -07:00
|
|
|
|
2026-06-19 17:51:51 -07:00
|
|
|
auto* text = new wxStaticText(this, wxID_ANY,
|
|
|
|
|
"Installing jailbreak, this will take a moment. If the device asks for a passcode\nplease enter it. Do not disconnect the device until finished.");
|
|
|
|
|
|
2026-06-26 20:55:55 -07:00
|
|
|
m_statusText = new wxStaticText(this, wxID_ANY, "Idle.");
|
|
|
|
|
m_progressBar = new wxGauge(this, wxID_ANY, 100);
|
|
|
|
|
m_progressBar->SetValue(0);
|
2026-06-19 17:51:51 -07:00
|
|
|
|
|
|
|
|
m_backButton = new wxButton(this, wxID_ANY, "Back");
|
|
|
|
|
m_backButton->Disable();
|
2026-06-26 20:55:55 -07:00
|
|
|
|
|
|
|
|
m_backButton->Bind(wxEVT_BUTTON, [this, frame](wxCommandEvent&) {
|
|
|
|
|
m_statusText->SetLabel("Idle.");
|
|
|
|
|
m_progressBar->SetValue(0);
|
|
|
|
|
m_backButton->Disable();
|
2026-06-19 17:51:51 -07:00
|
|
|
frame->ShowMain();
|
|
|
|
|
});
|
|
|
|
|
|
2026-06-26 20:55:55 -07:00
|
|
|
root->Add(text, 0, wxALL, 10);
|
|
|
|
|
root->Add(m_statusText, 0, wxALL, 10);
|
|
|
|
|
root->Add(m_progressBar, 0, wxALL | wxEXPAND, 20);
|
2026-06-19 17:51:51 -07:00
|
|
|
|
|
|
|
|
root->AddStretchSpacer();
|
2026-06-26 20:55:55 -07:00
|
|
|
root->Add(m_backButton, 0, wxALL | wxALIGN_RIGHT, 10);
|
2026-06-19 17:51:51 -07:00
|
|
|
|
|
|
|
|
SetSizer(root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExploitPanel::SetDeviceState(const DeviceState& state)
|
|
|
|
|
{
|
|
|
|
|
DevicePanel::SetDeviceState(state);
|
|
|
|
|
|
2026-06-26 20:55:55 -07:00
|
|
|
if (!IsShown())
|
2026-06-19 17:51:51 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExploitPanel::StartExploit()
|
|
|
|
|
{
|
2026-06-26 20:55:55 -07:00
|
|
|
m_statusText->SetLabel("Starting...");
|
2026-06-19 17:51:51 -07:00
|
|
|
m_backButton->Disable();
|
|
|
|
|
|
|
|
|
|
std::thread([this]()
|
|
|
|
|
{
|
2026-06-26 20:55:55 -07:00
|
|
|
const auto deviceState = GetDeviceState();
|
|
|
|
|
if (!deviceState.connected || deviceState.mode != DeviceMode::DFU)
|
2026-06-19 17:51:51 -07:00
|
|
|
return;
|
2026-06-26 20:55:55 -07:00
|
|
|
|
|
|
|
|
shared_t state{};
|
|
|
|
|
atomic_init(&state.result, 0);
|
|
|
|
|
atomic_init(&state.stop, false);
|
|
|
|
|
atomic_init(&state.exploit_done, false);
|
|
|
|
|
atomic_init(&state.pongo_done, false);
|
|
|
|
|
atomic_init(&state.stage, STAGE_PREPARE);
|
|
|
|
|
|
|
|
|
|
std::thread worker([&]() {
|
|
|
|
|
exploit(&state);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
worker.detach();
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
int stage = atomic_load(&state.stage);
|
|
|
|
|
int progress = stage_to_progress(stage);
|
|
|
|
|
|
|
|
|
|
wxTheApp->CallAfter([this, stage, progress]() {
|
|
|
|
|
m_statusText->SetLabel(stage_to_string(stage));
|
|
|
|
|
m_progressBar->SetValue(progress);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (stage == STAGE_DONE) {
|
|
|
|
|
wxTheApp->CallAfter([this]() {
|
|
|
|
|
m_backButton->Enable();
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
}
|
2026-06-19 17:51:51 -07:00
|
|
|
}).detach();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // WITH_GUI
|