diff --git a/TegraRcmGUI.rc b/TegraRcmGUI.rc index 9caaf84..50029a0 100644 Binary files a/TegraRcmGUI.rc and b/TegraRcmGUI.rc differ diff --git a/TegraRcmGUI.sln b/TegraRcmGUI.sln new file mode 100644 index 0000000..e8a6474 --- /dev/null +++ b/TegraRcmGUI.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TegraRcmGUI", "TegraRcmGUI.vcxproj", "{2C091C5B-378F-44D0-91F2-53489BA7B83C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + Static Debug|x64 = Static Debug|x64 + Static Debug|x86 = Static Debug|x86 + Static Release|x64 = Static Release|x64 + Static Release|x86 = Static Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x64.ActiveCfg = Debug|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x64.Build.0 = Debug|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x86.ActiveCfg = Debug|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Debug|x86.Build.0 = Debug|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x64.ActiveCfg = Release|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x64.Build.0 = Release|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x86.ActiveCfg = Release|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Release|x86.Build.0 = Release|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x64.ActiveCfg = Debug|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x64.Build.0 = Debug|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x86.ActiveCfg = Debug|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Debug|x86.Build.0 = Debug|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x64.ActiveCfg = Release|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x64.Build.0 = Release|x64 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x86.ActiveCfg = Release|Win32 + {2C091C5B-378F-44D0-91F2-53489BA7B83C}.Static Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/TegraRcmGUI.vcxproj b/TegraRcmGUI.vcxproj index dec9e5c..a67ec94 100644 --- a/TegraRcmGUI.vcxproj +++ b/TegraRcmGUI.vcxproj @@ -99,6 +99,7 @@ true Version.lib;libusbK.lib $(LIBUSBK_DIR)\bin\lib\$(PlatformShortName.Replace('x64','amd64'))\;%(AdditionalLibraryDirectories) + $(OutDir)$(TargetName)$(TargetExt) false @@ -118,10 +119,13 @@ Disabled _WINDOWS;_DEBUG;%(PreprocessorDefinitions) true + $(LIBUSBK_DIR)\includes\;%(AdditionalIncludeDirectories) Windows true + $(OutDir)$(TargetName)$(TargetExt) + $(LIBUSBK_DIR)\bin\lib\$(PlatformShortName.Replace('x64','amd64'))\;%(AdditionalLibraryDirectories) false @@ -232,6 +236,7 @@ + diff --git a/TegraRcmGUI.vcxproj.filters b/TegraRcmGUI.vcxproj.filters index d9c0355..c9ae8a2 100644 --- a/TegraRcmGUI.vcxproj.filters +++ b/TegraRcmGUI.vcxproj.filters @@ -113,5 +113,8 @@ Resource Files + + Resource Files + \ No newline at end of file diff --git a/TegraRcmGUIDlg.cpp b/TegraRcmGUIDlg.cpp index 16f1552..16d0e39 100644 --- a/TegraRcmGUIDlg.cpp +++ b/TegraRcmGUIDlg.cpp @@ -16,12 +16,14 @@ using namespace std; TCHAR* PAYLOAD_FILE; int RCM_STATUS = -10; -int LOOP_WAIT = 0; BOOL WAITING_RECONNECT = FALSE; -BOOL AUTOINJECT_CURR= FALSE; -BOOL PREVENT_AUTOINJECT= TRUE; +BOOL AUTOINJECT = FALSE; +BOOL AUTOINJECT_CURR = FALSE; +BOOL PREVENT_AUTOINJECT = TRUE; BOOL DELAY_AUTOINJECT = FALSE; BOOL ASK_FOR_DRIVER = FALSE; +BOOL PAUSE_LKP_DEVICE = FALSE; + CString csPath; // CTegraRcmGUIDlg dialog @@ -39,7 +41,7 @@ void CTegraRcmGUIDlg::DoDataExchange(CDataExchange* pDX) DDX_Control(pDX, RCM_PIC_1, RCM_BITMAP1); DDX_Control(pDX, RCM_PIC_2, RCM_BITMAP2); DDX_Control(pDX, RCM_PIC_3, RCM_BITMAP3); - DDX_Control(pDX, RCM_PIC_4, RCM_BITMAP0); + DDX_Control(pDX, RCM_PIC_4, RCM_BITMAP0); DDX_Control(pDX, PAYLOAD_PATH, m_EditBrowse); } @@ -49,8 +51,9 @@ BEGIN_MESSAGE_MAP(CTegraRcmGUIDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_EN_CHANGE(PAYLOAD_PATH, &CTegraRcmGUIDlg::OnEnChangePath) - ON_BN_CLICKED(IDC_INJECT, &CTegraRcmGUIDlg::OnBnClickedButton) + ON_BN_CLICKED(IDC_INJECT, &CTegraRcmGUIDlg::InjectPayload) ON_BN_CLICKED(IDC_SHOFEL2, &CTegraRcmGUIDlg::OnBnClickedShofel2) + ON_BN_CLICKED(IDC_MOUNT_SD, &CTegraRcmGUIDlg::OnBnClickedMountSd) END_MESSAGE_MAP() @@ -60,8 +63,10 @@ BOOL CTegraRcmGUIDlg::OnInitDialog() { CDialog::OnInitDialog(); + // Accessibility EnableActiveAccessibility(); + // Get current directory TCHAR szPath[_MAX_PATH]; VERIFY(::GetModuleFileName(AfxGetApp()->m_hInstance, szPath, _MAX_PATH)); CString csPathf(szPath); @@ -69,29 +74,32 @@ BOOL CTegraRcmGUIDlg::OnInitDialog() if (nIndex > 0) csPath = csPathf.Left(nIndex); else csPath.Empty(); + // Initialize bitmap RCM_BITMAP0.SetBitmap(INIT_LOGO); RCM_BITMAP1.SetBitmap(RCM_NOT_DETECTED); RCM_BITMAP2.SetBitmap(DRIVER_KO); RCM_BITMAP3.SetBitmap(RCM_DETECTED); - + + // Check for APX driver at startup BOOL isDriverInstalled = LookForDriver(); if (!isDriverInstalled) InstallDriver(); - + + // Read & apply presets string value = GetPreset("AUTO_INJECT"); if (value == "TRUE") { + AUTOINJECT = TRUE; AUTOINJECT_CURR = TRUE; - CMFCButton*checkbox = (CMFCButton*)GetDlgItem(AUTO_INJECT); + CMFCButton*checkbox = (CMFCButton*)GetDlgItem(AUTOINJECT); checkbox->SetCheck(BST_CHECKED); } CString file(GetPreset("PAYLOAD_FILE").c_str()); this->GetDlgItem(PAYLOAD_PATH)->SetWindowTextW(file); //PREVENT_AUTOINJECT = TRUE; - + // Menu ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); - CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { @@ -106,11 +114,13 @@ BOOL CTegraRcmGUIDlg::OnInitDialog() } } + // Set icons SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon + // Start timer to check RCM status every second CTegraRcmGUIDlg::StartTimer(); - + return TRUE; } @@ -119,9 +129,6 @@ void CTegraRcmGUIDlg::OnSysCommand(UINT nID, LPARAM lParam) CDialog::OnSysCommand(nID, lParam); } -// If you add a minimize button to your dialog, you will need the code below -// to draw the icon. For MFC applications using the document/view model, -// this is automatically done for you by the framework. void CTegraRcmGUIDlg::OnPaint() { @@ -148,24 +155,19 @@ void CTegraRcmGUIDlg::OnPaint() CDialog::OnPaint(); } } - // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CTegraRcmGUIDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } - - const UINT ID_TIMER_MINUTE = 0x1001; const UINT ID_TIMER_SECONDS = 0x1000; - // Start the timers. void CTegraRcmGUIDlg::StartTimer() { // Set timer for Minutes. - SetTimer(ID_TIMER_MINUTE, 60 * 1000, 0); - + //SetTimer(ID_TIMER_MINUTE, 60 * 1000, 0); // Set timer for Seconds. SetTimer(ID_TIMER_SECONDS, 1000, 0); } @@ -178,37 +180,52 @@ void CTegraRcmGUIDlg::StopTimer() KillTimer(ID_TIMER_SECONDS); } +// // Timer Handler. void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent) { + // Each second if (nIDEvent == ID_TIMER_SECONDS) { - + // Exit when PAUSE_LKP_DEVICE flag is TRUE + if (PAUSE_LKP_DEVICE) return; + + // Get Auto inject checkbox value (checked, unchecked) CButton *m_ctlCheck = (CButton*)GetDlgItem(AUTO_INJECT); BOOL IsCheckChecked = (m_ctlCheck->GetCheck() == 1) ? true : false; + if (AUTOINJECT_CURR != IsCheckChecked) { + // Auto inject option enabled if (IsCheckChecked) { SetPreset("AUTO_INJECT", "TRUE"); + AUTOINJECT = TRUE; DELAY_AUTOINJECT = TRUE; } + // Auto inject option disabled else { SetPreset("AUTO_INJECT", "FALSE"); + AUTOINJECT = FALSE; DELAY_AUTOINJECT = FALSE; } + // Save current checkbox value AUTOINJECT_CURR = IsCheckChecked; } + // Get RCM device Status + // This feature has been developped by Rajkosto (copied from TegraRcmSmash) TegraRcmSmash device; int rc = device.RcmStatus(); - + + // Init & bitmap pointers CStatic*pCtrl1 = (CStatic*)GetDlgItem(RCM_PIC_1); CStatic*pCtrl2 = (CStatic*)GetDlgItem(RCM_PIC_2); CStatic*pCtrl3 = (CStatic*)GetDlgItem(RCM_PIC_3); - std::string s = ""; + + // RCM Status = "RCM detected" if (rc >= 0) { pCtrl1->ShowWindow(SW_HIDE); @@ -216,7 +233,10 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent) pCtrl3->ShowWindow(SW_SHOW); this->GetDlgItem(IDC_INJECT)->EnableWindow(TRUE); this->GetDlgItem(IDC_SHOFEL2)->EnableWindow(TRUE); + this->GetDlgItem(IDC_MOUNT_SD)->EnableWindow(TRUE); + } + // RCM Status = "USB Driver KO" else if (rc > -5) { pCtrl1->ShowWindow(SW_HIDE); @@ -224,12 +244,10 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent) pCtrl3->ShowWindow(SW_HIDE); this->GetDlgItem(IDC_INJECT)->EnableWindow(FALSE); this->GetDlgItem(IDC_SHOFEL2)->EnableWindow(FALSE); + this->GetDlgItem(IDC_MOUNT_SD)->EnableWindow(FALSE); s = "lbusbK driver is needed !"; - - - if (!ASK_FOR_DRIVER) InstallDriver(); - } + // RCM Status = "RCM not detected" else { pCtrl1->ShowWindow(SW_SHOW); @@ -237,25 +255,26 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent) pCtrl3->ShowWindow(SW_HIDE); this->GetDlgItem(IDC_INJECT)->EnableWindow(FALSE); this->GetDlgItem(IDC_SHOFEL2)->EnableWindow(FALSE); + this->GetDlgItem(IDC_MOUNT_SD)->EnableWindow(FALSE); s = "Waiting for Switch in RCM mode."; - string value = GetPreset("AUTO_INJECT"); - if (value == "TRUE") - { - DELAY_AUTOINJECT = TRUE; - } - } - + // Delay Auto inject if needed + if (AUTOINJECT) DELAY_AUTOINJECT = TRUE; + } + + // On change RCM status if (rc != RCM_STATUS) { CStatic*pCtrl0 = (CStatic*)GetDlgItem(RCM_PIC_4); pCtrl0->ShowWindow(SW_HIDE); + // Status changed to "RCM Detected" if (rc == 0) { CString file; this->GetDlgItem(PAYLOAD_PATH)->GetWindowTextW(file); + // Trigger auto inject if payload injection scheduled if (DELAY_AUTOINJECT && file.GetLength() > 0) { InjectPayload(); @@ -263,57 +282,63 @@ void CTegraRcmGUIDlg::OnTimer(UINT nIDEvent) } else { - s = "\nSelect a payload :"; - CA2T wt(s.c_str()); - SetDlgItemText(INFO_LABEL, wt); + SetDlgItemText(INFO_LABEL, TEXT("\nSelect a payload :")); } } + // Status changed to "RCM not detected" or "USB driver KO" + else if (!ASK_FOR_DRIVER) + { + // Ask for driver install if not installed yet + BOOL isDriverInstalled = LookForDriver(); + if (!isDriverInstalled) InstallDriver(); + } + // Status changed to "RCM not detected" -> Disable WAITING_RECONNECT flag if (rc <= -5) WAITING_RECONNECT = FALSE; } RCM_STATUS = rc; } } +// +// On change payload path void CTegraRcmGUIDlg::OnEnChangePath() { CString file; this->GetDlgItem(PAYLOAD_PATH)->GetWindowTextW(file); PAYLOAD_FILE = _tcsdup(file); - + if (!PREVENT_AUTOINJECT) { + // Save payload path CT2CA pszConvertedAnsiString(file); std::string file_c(pszConvertedAnsiString); SetPreset("PAYLOAD_FILE", file_c); } - - std::string s = "\nSelect a payload :"; + std::string s = "\nSelect a payload :"; CButton *m_ctlCheck = (CButton*)GetDlgItem(AUTO_INJECT); BOOL IsCheckChecked = (m_ctlCheck->GetCheck() == 1) ? true : false; + // If Auto inject option enabled if (IsCheckChecked && !PREVENT_AUTOINJECT) { + // Delay auto inject if RCM not detected if (RCM_STATUS != 0) { DELAY_AUTOINJECT = TRUE; s = "Payload injection scheduled.\nWaiting for RCM mode."; } + // Inject payload if RCM detected else InjectPayload(); } PREVENT_AUTOINJECT = FALSE; CA2T wt(s.c_str()); SetDlgItemText(INFO_LABEL, wt); - -} - - -void CTegraRcmGUIDlg::OnBnClickedButton() -{ - InjectPayload(); } +// +// User payload injection void CTegraRcmGUIDlg::InjectPayload() { if (WAITING_RECONNECT) @@ -326,121 +351,100 @@ void CTegraRcmGUIDlg::InjectPayload() } } - LOOP_WAIT = 1; - TCHAR* args[2]; - args[0] = TEXT(""); - args[1] = PAYLOAD_FILE; string s; - if (PAYLOAD_FILE == nullptr) { - s = "\nNo file selected !"; - CA2T wt(s.c_str()); - CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt); - LOOP_WAIT = 0; + SetDlgItemText(INFO_LABEL, TEXT("\nNo file selected !")); return; } - - TegraRcmSmash device; - int rc = device.SmashMain(2, args); - - + int rc = Smasher(PAYLOAD_FILE); if (rc >= 0) { s = "\nPayload injected !"; WAITING_RECONNECT = TRUE; } else - { + { s = "Error while injecting payload (RC=" + std::to_string(rc) + ")"; } CA2T wt(s.c_str()); CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt); - LOOP_WAIT = 0; } void CTegraRcmGUIDlg::OnBnClickedShofel2() { - LOOP_WAIT = 1; - - TCHAR szPath[_MAX_PATH]; - VERIFY(::GetModuleFileName(AfxGetApp()->m_hInstance, szPath, _MAX_PATH)); - CString csPath(szPath); - int nIndex = csPath.ReverseFind(_T('\\')); - if (nIndex > 0) { - csPath = csPath.Left(nIndex); - } - else { - csPath.Empty(); - } + TCHAR *exe_dir = GetAbsolutePath(TEXT(""), CSIDL_APPDATA); string s; - CString COREBOOT_FILE = csPath + _T("\\shofel2\\coreboot\\coreboot.rom"); - CString COREBOOT = _T("CBFS+") + COREBOOT_FILE; - CString PAYLOAD = csPath + _T("\\shofel2\\coreboot\\cbfs.bin"); + TCHAR *COREBOOT_FILE = GetAbsolutePath(TEXT("shofel2\\coreboot\\coreboot.rom"), CSIDL_APPDATA); + TCHAR *PAYLOAD = GetAbsolutePath(TEXT("shofel2\\coreboot\\cbfs.bin"), CSIDL_APPDATA); + CString COREBOOT_FILE2 = COREBOOT_FILE; + CString COREBOOT = _T("CBFS+") + COREBOOT_FILE2; + std::ifstream infile(COREBOOT_FILE); BOOL coreboot_exists = infile.good(); std::ifstream infile2(PAYLOAD); BOOL payload_exists = infile2.good(); if (!coreboot_exists || !payload_exists) { - s = "Linux kernel not found in \\shofel2 dir"; - CA2T wt(s.c_str()); - CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt); - - + SetDlgItemText(INFO_LABEL, TEXT("Linux coreboot not found in \\shofel2 dir")); CString message = _T("Kernel not found in shofel2 directory. Do you want to automatically download arch linux kernel from SoulCipher repo ?"); const int result = MessageBox(message, _T("Kernel not found"), MB_YESNOCANCEL | MB_ICONQUESTION); - if (result == IDYES) + if (result == IDYES) { PROCESS_INFORMATION pif; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); - CString download_script = csPath + _T("\\shofel2\\download.bat"); - BOOL bRet = CreateProcess(download_script, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pif); - } - - LOOP_WAIT = 0; - return; + TCHAR *download_script = GetAbsolutePath(TEXT("shofel2\\download.bat"), CSIDL_APPDATA); + BOOL bRet = CreateProcess(download_script, NULL, NULL, NULL, FALSE, 0, NULL, exe_dir, &si, &pif); + } + return; // TO-DO : Remove return for coreboot injection after download } - TCHAR* payload_f = _tcsdup(PAYLOAD); - TCHAR* coreboot_f = _tcsdup(COREBOOT); - TCHAR* args[5]; - args[0] = TEXT(""); - args[1] = TEXT("-w"); - args[2] = TEXT("--relocator="); - args[3] = payload_f; - args[4] = coreboot_f; + SetDlgItemText(INFO_LABEL, TEXT("Loading coreboot. Please wait.")); - TegraRcmSmash device; + //int rc = device.SmashMain(5, args); + TCHAR cmd[MAX_PATH] = TEXT("--relocator= \""); + lstrcat(cmd, _tcsdup(PAYLOAD)); + lstrcat(cmd, TEXT("\" \"CBFS:")); + lstrcat(cmd, _tcsdup(COREBOOT_FILE)); + lstrcat(cmd, TEXT("\"")); + int rc = Smasher(cmd); - s = "Loading coreboot. Please wait."; - CA2T wt(s.c_str()); - SetDlgItemText(INFO_LABEL, wt); - - int rc = device.SmashMain(5, args); if (rc >= 0 || rc < -7) { - s = "Coreboot loaded. Waiting for device..."; - CA2T wt(s.c_str()); - SetDlgItemText(INFO_LABEL, wt); + SetDlgItemText(INFO_LABEL, TEXT("Coreboot injected. Waiting 5s for device...")); Sleep(5000); - CString usb_loader = csPath + _T("\\shofel2\\imx_usb.bat"); PROCESS_INFORMATION pif; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); - BOOL bRet = CreateProcess(usb_loader, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pif); - if (bRet == 0) + TCHAR *imx_script = GetAbsolutePath(TEXT("shofel2\\imx_usb.bat"), CSIDL_APPDATA); + SetDlgItemText(INFO_LABEL, TEXT("Loading coreboot... Please wait.")); + BOOL ret = CreateProcess(imx_script, NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, exe_dir, &si, &pif); + int rc = -50; + if (NULL != ret) { - s = "Error while loading shofel2\\imx_usb.bat."; + WaitForSingleObject(pif.hProcess, INFINITE); + DWORD exit_code; + if (FALSE != GetExitCodeProcess(pif.hProcess, &exit_code)) + { + if (STILL_ACTIVE != exit_code) rc = exit_code; + } + else rc = -51; + CloseHandle(pif.hProcess); + CloseHandle(pif.hThread); + } + + if (rc == 0) + { + s = "\nCoreboot loaded !"; } else { - s = "\nPayload injected !"; + s = "Error while loading imx_usb.exe"; } } else @@ -450,15 +454,15 @@ void CTegraRcmGUIDlg::OnBnClickedShofel2() CA2T wt2(s.c_str()); SetDlgItemText(INFO_LABEL, wt2); - LOOP_WAIT = 0; } string CTegraRcmGUIDlg::GetPreset(string param) { - CString rfile = csPath + "\\presets.conf"; + TCHAR *rfile = GetAbsolutePath(TEXT("presets.conf"), CSIDL_APPDATA); CT2A rfile_c(rfile, CP_UTF8); TRACE(_T("UTF8: %S\n"), rfile_c.m_psz); + ifstream readFile(rfile_c); string readout; string search = param + "="; @@ -468,9 +472,9 @@ string CTegraRcmGUIDlg::GetPreset(string param) while (getline(readFile, readout)) { if (readout.find(search) != std::string::npos) { std::string delimiter = "="; - value = readout.substr(readout.find(delimiter)+1, readout.length()+1); + value = readout.substr(readout.find(delimiter) + 1, readout.length() + 1); } - } + } } readFile.close(); return value; @@ -478,9 +482,8 @@ string CTegraRcmGUIDlg::GetPreset(string param) void CTegraRcmGUIDlg::SetPreset(string param, string value) { - // Preset conf gfile - CString rfile = csPath + "\\presets.conf"; - CString wfile = csPath + "\\presets.conf.tmp"; + TCHAR *rfile = GetAbsolutePath(TEXT("presets.conf"), CSIDL_APPDATA); + TCHAR *wfile = GetAbsolutePath(TEXT("presets.conf.tmp"), CSIDL_APPDATA); CT2A rfile_c(rfile, CP_UTF8); TRACE(_T("UTF8: %S\n"), rfile_c.m_psz); CT2A wfile_c(wfile, CP_UTF8); @@ -491,7 +494,7 @@ void CTegraRcmGUIDlg::SetPreset(string param, string value) ifstream readFile(rfile_c); string readout; string search = param + "="; - string replace = "\n" + search + value; + string replace = "\n" + search + value + "\n"; BOOL found = FALSE; while (getline(readFile, readout)) { if (readout.find(search) != std::string::npos) { @@ -522,7 +525,7 @@ void CTegraRcmGUIDlg::InstallDriver() shExInfo.cbSize = sizeof(shExInfo); shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shExInfo.hwnd = 0; - shExInfo.lpVerb = _T("runas"); + shExInfo.lpVerb = _T("runas"); CString exe_file = csPath + _T("\\apx_driver\\InstallDriver.exe"); shExInfo.lpFile = exe_file; shExInfo.lpDirectory = 0; @@ -541,14 +544,72 @@ typedef int(__cdecl *MYPROC)(LPWSTR); BOOL CTegraRcmGUIDlg::LookForDriver() { - TCHAR system_dir[MAX_PATH]; - HRESULT result = SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, system_dir); - if (result != S_OK) return FALSE; - PathAppend(system_dir, _T("\\libusbK.dll")); - - - std::ifstream infile32(system_dir); - BOOL file_exists32 = infile32.good(); - if (!file_exists32) return FALSE; - + TCHAR *system_dir = GetAbsolutePath(TEXT("libusbK.dll"), CSIDL_SYSTEM); + std::ifstream infile(system_dir); + BOOL file_exists = infile.good(); + return file_exists; +} + + +void CTegraRcmGUIDlg::OnBnClickedMountSd() +{ + string s; + TCHAR args[] = TEXT("memloader\\memloader_usb.bin -r --dataini=memloader\\ums_sd.ini"); + int rc = Smasher(args); + if (rc < 0) s = "Error while loading payload (RC=" + std::to_string(rc) + ")"; + else s = "SD tool (by rajkosto) injected"; + CA2T wt(s.c_str()); + CTegraRcmGUIDlg::SetDlgItemText(INFO_LABEL, wt); +} + +int CTegraRcmGUIDlg::Smasher(TCHAR args[]) +{ + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + PROCESS_INFORMATION pi; + STARTUPINFO si; + BOOL ret = FALSE; + DWORD flags = CREATE_NO_WINDOW; + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.dwFlags |= STARTF_USESTDHANDLES; + si.hStdInput = NULL; + TCHAR cmd[MAX_PATH] = TEXT(".\\TegraRcmSmash.exe "); + lstrcat(cmd, args); + ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi); + int rc = -50; + if (NULL != ret) + { + WaitForSingleObject(pi.hProcess, INFINITE); + DWORD exit_code; + if (FALSE != GetExitCodeProcess(pi.hProcess, &exit_code)) + { + if (STILL_ACTIVE != exit_code) + { + rc = exit_code; + } + } + else + { + rc = -51; + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + return rc; +} + +TCHAR* CTegraRcmGUIDlg::GetAbsolutePath(TCHAR* relative_path, DWORD dwFlags) +{ + TCHAR szPath[MAX_PATH]; + if (SUCCEEDED(SHGetFolderPath(NULL, dwFlags, NULL, SHGFP_TYPE_CURRENT, szPath))) + { + if (dwFlags == CSIDL_APPDATA) PathAppend(szPath, _T("\\TegraRcmGUI")); + PathAppend(szPath, relative_path); + return _tcsdup(szPath); + } + return _T(""); } diff --git a/TegraRcmGUIDlg.h b/TegraRcmGUIDlg.h index 87dc10a..e7f2fd1 100644 --- a/TegraRcmGUIDlg.h +++ b/TegraRcmGUIDlg.h @@ -3,11 +3,11 @@ // #pragma once #include "res/BitmapPicture.h" -#include +#include #include "TegraRcmSmash.h" #include "res/BitmapPicture.h" #include -#include +#include #include #include #include @@ -23,7 +23,7 @@ // CTegraRcmGUIDlg dialog class CTegraRcmGUIDlg : public CDialog { -// Construction + // Construction public: CTegraRcmGUIDlg(CWnd* pParent = NULL); // standard constructor CBitmapPicture RCM_BITMAP0; @@ -32,20 +32,20 @@ public: CBitmapPicture RCM_BITMAP3; CMFCEditBrowseCtrl m_EditBrowse; -// Dialog Data + // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_TEGRARCMGUI_DIALOG }; #endif - protected: +protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support -// Implementation + // Implementation protected: HICON m_hIcon; - // Generated message map functions - virtual BOOL OnInitDialog(); + // Generated message map functions + virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnIdle(); afx_msg void OnShowWindow(); @@ -58,11 +58,13 @@ public: void OnTimer(UINT nIDEvent); int STATUS; afx_msg void OnEnChangePath(); - afx_msg void OnBnClickedButton(); afx_msg void InjectPayload(); afx_msg void OnBnClickedShofel2(); afx_msg string GetPreset(string param); afx_msg void SetPreset(string param, string value); afx_msg void InstallDriver(); afx_msg BOOL LookForDriver(); + afx_msg void OnBnClickedMountSd(); + afx_msg int Smasher(TCHAR args[]); + afx_msg TCHAR* GetAbsolutePath(TCHAR *relative_path, DWORD dwFlags); }; diff --git a/TegraRcmSmash.cpp b/TegraRcmSmash.cpp index e6e3415..74d2373 100644 --- a/TegraRcmSmash.cpp +++ b/TegraRcmSmash.cpp @@ -2,11 +2,12 @@ * TegraRcmShash.cpp (by rajkosto) * A reimplementation of fusee-launcher by ktemkin in C++ for Windows platforms. * https://github.com/rajkosto/TegraRcmSmash + * + * */ #include "stdafx.h" #include "TegraRcmSmash.h" - class RCMDeviceHacker { public: @@ -252,7 +253,7 @@ int TegraRcmSmash::RcmStatus() if (deviceCount == 0 || LstK_FindByVidPid(deviceList, deviceVid, devicePid, &deviceInfo) == FALSE) { // No device found in RCM Mode - return -5; + return -5; } if (deviceInfo != nullptr) @@ -289,7 +290,7 @@ int TegraRcmSmash::RcmStatus() } else if (usbkVersion.major != 3 || usbkVersion.minor != 0 || usbkVersion.micro != 7) { - + // Wrong USB driver version return -1; } @@ -297,848 +298,4 @@ int TegraRcmSmash::RcmStatus() return 0; -} - -int TegraRcmSmash::SmashMain(int argc, TCHAR* argv[]) -{ -#ifdef UNICODE - fflush(stdout); - _setmode(_fileno(stdout), _O_WTEXT); - fflush(stderr); - _setmode(_fileno(stderr), _O_WTEXT); -#endif - const TCHAR DEFAULT_MEZZO_FILENAME[] = TEXT("intermezzo.bin"); - const TCHAR* mezzoFilename = DEFAULT_MEZZO_FILENAME; - const TCHAR* inputFilename = nullptr; - bool waitForDevice = false; - struct AdditionalDataItem - { - const TCHAR* filename = nullptr; - u32 address = 0; - u16 strTerm = 0; - bool reloaded = false; - ByteVector dataBytes; - - bool isBOOT() const { return memcmp(&address, "BOOT", strlen("BOOT") + 1) == 0; } - void setBOOT() { memcpy(&address, "BOOT", strlen("BOOT")); strTerm = 0; } - - bool isAddr() const { return strTerm != 0; } - void setAddr(u32 newAddr) { address = newAddr; strTerm = 1; } - void setSect(const char* sectName) { memset(&address, 0, sizeof(address)); memcpy(&address, sectName, strlen(sectName)); strTerm = 0; } - const char* getSect() const { return (const char*)&address; } - }; - vector moreData; - - auto PrintUsage = []() -> int - { - //_tprintf(TEXT("Usage: TegraRcmSmash.exe [-V 0x0955] [-P 0x7321] [--relocator=intermezzo.bin] [-w] inputFilename.bin ([PARAM:VALUE]|[0xADDR:filename])*\n")); - return -1; - }; - - const TCHAR HEXA_PREFIX[] = TEXT("0x"); - for (int i = 1; i= array_countof(HEXA_PREFIX) && - _tcsnicmp(numberValueStr, HEXA_PREFIX, array_countof(HEXA_PREFIX) - 1) == 0) - numberValueStr += array_countof(HEXA_PREFIX) - 1; - - if (matchedStr == VENDOR_ARGUMENT) - deviceVid = _tcstoul(numberValueStr, nullptr, 0x10); - else if (matchedStr == PRODUCT_ARGUMENT) - devicePid = _tcstoul(numberValueStr, nullptr, 0x10); - else - return PrintUsage(); - } - else if (_tcsnicmp(currArg, WAIT_ARGUMENT, array_countof(WAIT_ARGUMENT)) == 0) - { - waitForDevice = true; - } - else if (currArg[0] == '-') //unknown option - { - //_ftprintf(stderr, TEXT("Unknown option %Ts\n"), currArg); - return PrintUsage(); - } - else //payload/data filename - { - if (inputFilename == nullptr) - inputFilename = currArg; - else - { - auto colonPos = _tcschr(currArg, '+'); - if (colonPos == nullptr) - { - //_ftprintf(stderr, TEXT("No colon separator in additional data argument '%Ts'\n"), currArg); - return PrintUsage(); - } - - *colonPos = 0; - const size_t leftPartLen = colonPos - currArg; - const TCHAR* leftPart = currArg; - const TCHAR* rightPart = colonPos + 1; - - AdditionalDataItem newItem; - newItem.filename = rightPart; - if (leftPartLen >= array_countof(HEXA_PREFIX) && - _tcsnicmp(leftPart, HEXA_PREFIX, array_countof(HEXA_PREFIX) - 1) == 0) - { - leftPart += array_countof(HEXA_PREFIX) - 1; - - wchar_t* endPos = nullptr; - newItem.setAddr(_tcstoul(leftPart, &endPos, 0x10)); - if (endPos == nullptr || endPos == leftPart) - { - //_ftprintf(stderr, TEXT("Invalid load address '%Ts' in additional data argument '%Ts'\n"), leftPart, currArg); - return -1; - } - - auto it = std::find_if(moreData.cbegin(), moreData.cend(), [&newItem](const AdditionalDataItem& itm) { - return (itm.isAddr() == newItem.isAddr()) && (itm.address == newItem.address); - }); - - if (it != moreData.cbegin()) - { - //_ftprintf(stderr, TEXT("Load address 0x%08x already defined with filename '%Ts'\n"), it->address, it->filename); - return -1; - } - - moreData.emplace_back(std::move(newItem)); - } - else if (leftPartLen <= sizeof(newItem.address)) - { - std::string convAscii; convAscii.reserve(_tcslen(leftPart)); - for (size_t strPos = 0; strPosgetSect(), it->filename); - return -1; - } - - moreData.emplace_back(std::move(newItem)); - } - else - { - //_ftprintf(stderr, TEXT("Invalid param name '%Ts' in additional data argument '%Ts'\n"), leftPart, currArg); - return -1; - } - } - } - } - - //print program name and version - { - TCHAR stringBuf[2048]; - stringBuf[0] = 0; - const auto numChars = GetModuleFileName(NULL, stringBuf, (DWORD)array_countof(stringBuf) - 1); - stringBuf[numChars] = 0; - - const TCHAR* versionInfoStr = TEXT("[UNKNOWN VERSION]"); - if (GetFileVersionInfo(stringBuf, 0, sizeof(stringBuf), stringBuf)) - { - VS_FIXEDFILEINFO* fileInfo = nullptr; - unsigned int infoLen = 0; - if (VerQueryValue(stringBuf, TEXT("\\"), (LPVOID*)&fileInfo, &infoLen) && fileInfo != nullptr && infoLen > 0) - { - const u32 outMajor = HIWORD(fileInfo->dwFileVersionMS); - const u32 outMinor = LOWORD(fileInfo->dwFileVersionMS); - const u32 outRev = HIWORD(fileInfo->dwFileVersionLS); - const u32 outBld = LOWORD(fileInfo->dwFileVersionLS); - - //_stprintf_s(stringBuf, TEXT("%u.%u.%u-%u"), outMajor, outMinor, outRev, outBld); - versionInfoStr = stringBuf; - } - } - - const TCHAR* bitnessStr = nullptr; -#if !_WIN64 - bitnessStr = TEXT("32bit"); -#else - bitnessStr = TEXT("64bit"); -#endif - //_tprintf(TEXT("TegraRcmSmash (%Ts) %Ts by rajkosto\n"), bitnessStr, versionInfoStr); - } - - //check all arguments - if (deviceVid == 0 || deviceVid >= 0xFFFF) - { - _ftprintf(stderr, TEXT("Invalid USB VID specified\n")); - return PrintUsage(); - } - if (devicePid == 0 || devicePid >= 0xFFFF) - { - _ftprintf(stderr, TEXT("Invalid USB PID specified\n")); - return PrintUsage(); - } - if (inputFilename == nullptr || _tcslen(inputFilename) == 0) - { - _ftprintf(stderr, TEXT("Please specify input filename\n")); - return PrintUsage(); - } - - std::sort(moreData.begin(), moreData.end(), [](const AdditionalDataItem& left, const AdditionalDataItem& right) { - if (left.isBOOT() != right.isBOOT()) //boot goes last - { - if (left.isBOOT()) - return false; - if (right.isBOOT()) - return true; - } - - if (left.isAddr() != right.isAddr()) //named go first - { - if (left.isAddr()) - return false; - if (right.isAddr()) - return true; - } - - if (left.isAddr()) - return left.address < right.address; - else - return (strcmp(left.getSect(), right.getSect()) < 0); - }); - - auto ReadFileToBuf = [](ByteVector& outBuf, const TCHAR* fileType, const TCHAR* inputFilename, bool silent) -> int - { - std::ifstream inputFile(inputFilename, std::ios::binary); - if (!inputFile.is_open()) - { - if (!silent) - _ftprintf(stderr, TEXT("Couldn't open %Ts file '%Ts' for reading\n"), fileType, inputFilename); - - return -2; - } - - inputFile.seekg(0, std::ios::end); - const auto inputSize = inputFile.tellg(); - inputFile.seekg(0, std::ios::beg); - - outBuf.resize((size_t)inputSize); - if (outBuf.size() > 0) - { - inputFile.read((char*)&outBuf[0], outBuf.size()); - const auto bytesRead = inputFile.gcount(); - if (bytesRead < inputSize) - { - _ftprintf(stderr, TEXT("Error reading %Ts file '%Ts' (only %llu out of %llu bytes read)\n"), fileType, inputFilename, (u64)bytesRead, (u64)inputSize); - return -2; - } - } - - return 0; - }; - - //populate address for BOOT if necessary, otherwise load file contents - for (size_t i = 0; i= array_countof(HEXA_PREFIX) && - _tcsnicmp(currData.filename, HEXA_PREFIX, array_countof(HEXA_PREFIX) - 1) == 0) - { - auto addressStr = currData.filename + array_countof(HEXA_PREFIX) - 1; - - wchar_t* endPos = nullptr; - currData.setAddr(_tcstoul(addressStr, &endPos, 0x10)); - if (endPos == nullptr || endPos == addressStr) - { - _ftprintf(stderr, TEXT("Invalid parameter address '%Ts' for setting '%hs'\n"), addressStr, currData.getSect()); - return -1; - } - } - else - { - bool foundAddress = false; - for (size_t j = 0; jDriverID != KUSB_DRVID_LIBUSBK) - { - /* - _tprintf(TEXT("The selected device path %hs with VID_%04X&PID_%04x isn't using the libusbK driver\n"), - deviceInfo->DevicePath, deviceInfo->Common.Vid, deviceInfo->Common.Pid); - _tprintf(TEXT("Please run Zadig and install the libusbK (v3.0.7.0) driver for this device\n")); - - _ftprintf(stderr,TEXT("Failed to open USB device handle because of wrong driver installed\n")); - */ - return -6; - } - - KUSB_DRIVER_API Usb; - LibK_LoadDriverAPI(&Usb, deviceInfo->DriverID); - - // Initialize the device - KUSB_HANDLE handle = nullptr; - if (!Usb.Init(&handle, deviceInfo)) - { - const auto errorCode = GetLastError(); - _ftprintf(stderr, TEXT("Failed to open USB device handle with win32 error %u\n"), errorCode); - return -6; - } - - RCMDeviceHacker rcmDev(Usb, handle); handle = nullptr; - - libusbk::version_t usbkVersion; - memset(&usbkVersion, 0, sizeof(usbkVersion)); - const auto versRetVal = rcmDev.getDriverVersion(usbkVersion); - if (versRetVal <= 0) - { - _ftprintf(stderr, TEXT("Failed to get libusbK driver version for device with win32 error %d\n"), -versRetVal); - return -6; - } - else if (usbkVersion.major != 3 || usbkVersion.minor != 0 || usbkVersion.micro != 7) - { - /* - _tprintf(TEXT("The opened device isn't using the correct libusbK driver version (expected: %u.%u.%u got: %u.%u.%u)\n"), - 3, 0, 7, usbkVersion.major, usbkVersion.minor, usbkVersion.micro); - _tprintf(TEXT("Please run Zadig and install the libusbK (v3.0.7.0) driver for this device\n")); - - _ftprintf(stderr, TEXT("Failed to open USB device handle because of wrong driver version installed\n")); - */ - return -6; - } - - u8 didBuf[0x10]; - memset(didBuf, 0, sizeof(didBuf)); - const auto didRetVal = rcmDev.readDeviceId(didBuf, sizeof(didBuf)); - if (didRetVal >= int(sizeof(didBuf))) - { - /* - _tprintf(TEXT("RCM Device with id %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X initialized successfully!\n"), - (u32)didBuf[0],(u32)didBuf[1],(u32)didBuf[2],(u32)didBuf[3],(u32)didBuf[4],(u32)didBuf[5],(u32)didBuf[6],(u32)didBuf[7], - (u32)didBuf[8],(u32)didBuf[9],(u32)didBuf[10],(u32)didBuf[11],(u32)didBuf[12],(u32)didBuf[13],(u32)didBuf[14],(u32)didBuf[15]); - */ - } - else - { - if (didRetVal < 0) - _ftprintf(stderr, TEXT("Reading device id failed with win32 error %d\n"), -didRetVal); - else - _ftprintf(stderr, TEXT("Was only able to read %d out of %d bytes of device id\n"), didRetVal, (int)sizeof(didBuf)); - - return -7; - } - - size_t currPayloadOffs = 0; - ByteVector payloadBuf; - - // Prefix the image with an RCM command, so it winds up loaded into memory at the right location (0x40010000). - // Use the maximum length accepted by RCM, so we can transmit as much payload as we want; we'll take over before we get to the end. - { - const u32 lengthData = 0x30298; - payloadBuf.resize(payloadBuf.size() + sizeof(lengthData)); - memcpy(&payloadBuf[currPayloadOffs], &lengthData, sizeof(lengthData)); - currPayloadOffs += sizeof(lengthData); - } - - // pad out to 680 so the payload starts at the right address in IRAM - payloadBuf.resize(680, 0); - currPayloadOffs = payloadBuf.size(); - - constexpr u32 RCM_PAYLOAD_ADDR = 0x40010000; - if (usingNoMezzo) - { - constexpr size_t bytesToAdd = 0x1a3a * sizeof(u32); - payloadBuf.resize(payloadBuf.size() + bytesToAdd, 0); - currPayloadOffs += bytesToAdd; - assert(currPayloadOffs == payloadBuf.size()); - - // Reload the user-supplied binary in case it changed - readFileRes = ReadFileToBuf(userFileBuf, TEXT("payload"), inputFilename, false); - if (readFileRes != 0) - return readFileRes; - - u32 entry = RCM_PAYLOAD_ADDR + (u32)userFileBuf.size() + sizeof(u32); - entry |= 1; //we want to jump to thumb code - - payloadBuf.resize(payloadBuf.size() + sizeof(u32)); - memcpy(&payloadBuf[currPayloadOffs], &entry, sizeof(entry)); - currPayloadOffs += sizeof(entry); - assert(currPayloadOffs == payloadBuf.size()); - } - else - { - constexpr u32 INTERMEZZO_LOCATION = 0x4001F000; - // Populate from[RCM_PAYLOAD_ADDR, INTERMEZZO_LOCATION) with the payload address. - // We'll use this data to smash the stack when we execute the vulnerable memcpy. - { - constexpr size_t bytesToAdd = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDR); - payloadBuf.resize(payloadBuf.size() + bytesToAdd); - while (currPayloadOffs < payloadBuf.size()) - { - const u32 spreadMeAround = INTERMEZZO_LOCATION; - memcpy(&payloadBuf[currPayloadOffs], &spreadMeAround, sizeof(spreadMeAround)); - currPayloadOffs += sizeof(spreadMeAround); - } - } - - // Reload the user-supplied relocator in case it changed - if (!usingBuiltinMezzo) - { - readFileRes = ReadFileToBuf(mezzoBuf, TEXT("relocator"), mezzoFilename, false); - if (readFileRes != 0) - return readFileRes; - } - - // Include the Intermezzo binary in the command stream. This is our first-stage payload, and it's responsible for relocating the final payload to 0x40010000. - { - payloadBuf.resize(payloadBuf.size() + mezzoBuf.size()); - if (currPayloadOffs < payloadBuf.size()) - { - memcpy(&payloadBuf[currPayloadOffs], &mezzoBuf[0], mezzoBuf.size()); - currPayloadOffs += mezzoBuf.size(); - } - assert(currPayloadOffs == payloadBuf.size()); - } - - constexpr u32 PAYLOAD_LOAD_BLOCK = 0x40020000; - // Finally, pad until we've reached the position we need to put the payload. - // This ensures the payload winds up at the location Intermezzo expects. - { - const auto position = INTERMEZZO_LOCATION + mezzoBuf.size(); - const auto paddingSize = PAYLOAD_LOAD_BLOCK - position; - - payloadBuf.resize(payloadBuf.size() + paddingSize, 0); - currPayloadOffs += paddingSize; - assert(currPayloadOffs == payloadBuf.size()); - } - - // Reload the user-supplied binary in case it changed - readFileRes = ReadFileToBuf(userFileBuf, TEXT("payload"), inputFilename, false); - if (readFileRes != 0) - return readFileRes; - } - - // Put our user-supplied binary into the payload - { - payloadBuf.resize(payloadBuf.size() + userFileBuf.size()); - if (currPayloadOffs < payloadBuf.size()) - { - memcpy(&payloadBuf[currPayloadOffs], &userFileBuf[0], userFileBuf.size()); - currPayloadOffs += userFileBuf.size(); - } - assert(currPayloadOffs == payloadBuf.size()); - } - - constexpr size_t PAYLOAD_TOTAL_MAX_SIZE = 192 * 1024; - // Pad the payload to fill a USB request exactly, so we don't send a short - // packet and break out of the RCM loop. - if (payloadBuf.size() < PAYLOAD_TOTAL_MAX_SIZE) - payloadBuf.resize(align_up(payloadBuf.size(), RCMDeviceHacker::PACKET_SIZE), 0); - else - payloadBuf.resize(PAYLOAD_TOTAL_MAX_SIZE); - - // Send the constructed payload, which contains the command, the stack smashing values, the Intermezzo relocation stub, and the user payload. - //_tprintf(TEXT("Uploading payload (mezzo size: %u, user size: %u, total size: %u, total padded size: %u)...\n"), - //(u32)mezzoBuf.size(), (u32)userFileBuf.size(), (u32)currPayloadOffs, (u32)payloadBuf.size()); - - const auto writeRes = rcmDev.write(&payloadBuf[0], payloadBuf.size()); - if (writeRes < (int)payloadBuf.size()) - { - if (writeRes < 0) { - //_ftprintf(stderr, TEXT("Win32 error %d happened trying to write payload buffer to RCM\n"), -writeRes); - } - else - { - //_ftprintf(stderr, TEXT("Was only able to upload %d out of %d bytes of payload buffer\n"), writeRes, (int)payloadBuf.size()); - return -8; - } - } - - // The RCM backend alternates between two different DMA buffers.Ensure we're about to DMA into the higher one, so we have less to copy during our attack. - const auto switchRes = rcmDev.switchToHighBuffer(); - if (switchRes != 0) - { - if (switchRes < 0) - { - //_ftprintf(stderr, TEXT("Failed to switch to high buffer, win32 error %d\n"), -switchRes); - return -9; - } - else if (switchRes != RCMDeviceHacker::PACKET_SIZE) - { - //_ftprintf(stderr, TEXT("Only wrote %d out of %d bytes during high buffer switch\n"), switchRes, (int)RCMDeviceHacker::PACKET_SIZE); - return -9; - } - - //_tprintf(TEXT("Switched to high buffer\n")); - } - - //_tprintf(TEXT("Smashing the stack!\n")); - const auto smashRes = rcmDev.smashTheStack(); - if (smashRes < 0) - { - //_ftprintf(stderr, TEXT("Got win32 error %d tryin to smash\n"), -smashRes); - return -10; - } - - //_tprintf(TEXT("Smashed the stack with a 0x%04x byte SETUP request!\n"), smashRes); - - if (moreData.size() > 0) - { - ByteVector readBuffer(32768, 0); - int bytesRead = 0; - while ((bytesRead = rcmDev.read(&readBuffer[0], readBuffer.size())) > 0) - { - auto dataIt = std::find_if(moreData.begin(), moreData.end(), [bytesRead, &readBuffer](const AdditionalDataItem& itm) - { - if (itm.isAddr() || itm.isBOOT()) - return false; - - const char* dataName = itm.getSect(); - const size_t dataNameLen = strlen(dataName); - if (bytesRead > int(dataNameLen) && readBuffer[dataNameLen] == '\n' && - strncmp((const char*)&readBuffer[0], dataName, dataNameLen) == 0) - return true; - - return false; - }); - - static const char READY_INDICATOR[] = "READY.\n"; - if (bytesRead == array_countof(READY_INDICATOR) - 1 && memcmp(&readBuffer[0], READY_INDICATOR, array_countof(READY_INDICATOR) - 1) == 0) - { - //_tprintf(TEXT("Switching to command mode due to %hs"), READY_INDICATOR); - for (auto& currData : moreData) - { - if (!currData.isAddr() && !currData.isBOOT()) - continue; - - if (!currData.isBOOT()) - { - if (!currData.reloaded) - { - readFileRes = ReadFileToBuf(currData.dataBytes, TEXT("data"), currData.filename, false); - if (readFileRes != 0) - return readFileRes; - - currData.reloaded = true; - } - - //_tprintf(TEXT("Sending %Ts (%llu bytes) to address 0x%08x\n"), currData.filename, (u64)currData.dataBytes.size(), currData.address); - if (currData.dataBytes.size() == 0) - continue; - - int bytesSent = rcmDev.write((const u8*)"RECV", strlen("RECV")); - if (bytesSent == strlen("RECV")) - { - u32 offsetData[] = { _byteswap_ulong((u32)currData.address), _byteswap_ulong((u32)currData.dataBytes.size()) }; - bytesSent = rcmDev.write((const u8*)&offsetData[0], sizeof(offsetData)); - if (bytesSent == sizeof(offsetData)) - bytesSent = rcmDev.write(&currData.dataBytes[0], currData.dataBytes.size(), readBuffer.size()); - } - if (bytesSent != int(currData.dataBytes.size())) - { - if (bytesSent < 0) - { - //_ftprintf(stderr, TEXT("Got win32 err %d during send operation!\n"), -bytesSent); - return -10; - } - else if (size_t(bytesSent) < currData.dataBytes.size()) - { - //_ftprintf(stderr, TEXT("Only sent %d out of %llu bytes for data file %Ts!\n"), bytesSent, (u64)currData.dataBytes.size(), currData.filename); - continue; - } - } - } - else - { - //_tprintf(TEXT("Booting AArch64 with PC 0x%08x...\n"), currData.address); - int bytesSent = rcmDev.write((const u8*)"BOOT", strlen("BOOT")); - if (bytesSent == strlen("BOOT")) - { - u32 addrData = _byteswap_ulong(currData.address); - bytesSent = rcmDev.write((const u8*)&addrData, sizeof(addrData)); - if (bytesSent == sizeof(addrData)) - { - //_tprintf(TEXT("BOOT command sent successfully! Exiting.\n")); - return 0; - } - } - } - } - } - else if (dataIt == moreData.end()) //no matching section to send, just print out the message - { - WinString printMe((const char*)&readBuffer[0], (const char*)&readBuffer[bytesRead]); - //_tprintf(printMe.c_str()); - } - else //got a section to send - { - //_tprintf(TEXT("Switching to sending of section '%hs'\n"), dataIt->getSect()); - if (!dataIt->reloaded) - { - readFileRes = ReadFileToBuf(dataIt->dataBytes, TEXT("data"), dataIt->filename, false); - if (readFileRes != 0) - return readFileRes; - - dataIt->reloaded = true; - } - - size_t numBytesSent = 0; - while ((bytesRead = rcmDev.read(&readBuffer[0], readBuffer.size())) >= 8) - { - u32 offset, length; - memcpy(&offset, &readBuffer[0], sizeof(offset)); - memcpy(&length, &readBuffer[sizeof(offset)], sizeof(length)); - offset = _byteswap_ulong(offset); - length = _byteswap_ulong(length); - - if (length == 0) - { - //_tprintf(TEXT("Finished sending section '%hs' (total bytes sent: %llu)\n"), dataIt->getSect(), (u64)numBytesSent); - break; - } - - const auto neededBytes = size_t(offset) + size_t(length); - if (neededBytes > dataIt->dataBytes.size()) - { - //_ftprintf(stderr, TEXT("Device requested %llu bytes (we only have %llu in file '%Ts')!\n"), (u64)neededBytes, (u64)dataIt->dataBytes.size(), dataIt->filename); - return -2; - } - - //_tprintf(TEXT("Sending 0x%08x bytes from offset 0x%08x\n"), length, offset); - int bytesSent = rcmDev.write(&dataIt->dataBytes[offset], length, readBuffer.size()); - if (bytesSent != int(length)) - { - if (bytesSent >= 0) - { - //_ftprintf(stderr, TEXT("Warn: Sent only %d out of requested %u bytes\n"), bytesSent, length); - } - else - { - //_ftprintf(stderr, TEXT("Got win32 err %d during send operation!\n"), -bytesSent); - return -10; - } - } - numBytesSent += bytesSent; - } - if (bytesRead < 0) - { - //_ftprintf(stderr, TEXT("Got win32 err %d during [offset,length] read operation!\n"), -bytesRead); - return -10; - } - else if (bytesRead < 8) - { - //_ftprintf(stderr, TEXT("Read too short packet (%d bytes) while in section send mode, dropping out.\n"), bytesRead); - break; - } - } - } - if (bytesRead < 0) - { - //_ftprintf(stderr, TEXT("Win32 error %d during post-smash read op\n"), -bytesRead); - return -10; - } - } - } - - return 0; } \ No newline at end of file diff --git a/TegraRcmSmash.h b/TegraRcmSmash.h index 7e5e8fa..c5b3de6 100644 --- a/TegraRcmSmash.h +++ b/TegraRcmSmash.h @@ -18,7 +18,5 @@ public: TegraRcmSmash(); ~TegraRcmSmash(); static int RcmStatus(); - static int Smash(TCHAR* payload, CString coreboot = _T("")); - static int SmashMain(int argc, TCHAR* argv[]); }; diff --git a/resource.h b/resource.h index f397f02..ec108d6 100644 Binary files a/resource.h and b/resource.h differ