forked from batteryshark/chdssf
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSSFHelper_m3u_support.cpp
More file actions
154 lines (126 loc) · 5.02 KB
/
SSFHelper_m3u_support.cpp
File metadata and controls
154 lines (126 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* SSF Helper - Launch SSF with CHD and M3U support
*/
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <Windows.h>
#include <commdlg.h>
static char inject_dll_path[4096];
static char full_exe_path[4096];
static std::string chd_file_path;
void createShellcode(int ret, int str, unsigned char** shellcode, int* shellcodeSize)
{
auto* retChar = reinterpret_cast<unsigned char*>(&ret);
auto* strChar = reinterpret_cast<unsigned char*>(&str);
int api = reinterpret_cast<int>(GetProcAddress(LoadLibraryA("kernel32.dll"), "LoadLibraryA"));
auto* apiChar = reinterpret_cast<unsigned char*>(&api);
unsigned char sc[] = {
// Push ret
0x68, retChar[0], retChar[1], retChar[2], retChar[3],
// Push all flags
0x9C,
// Push all register
0x60,
// Push 0x66666666 (later we convert it to the string of injected dll)
0x68, strChar[0], strChar[1], strChar[2], strChar[3],
// Mov eax, 0x66666666 (later we convert it to LoadLibrary address)
0xB8, apiChar[0], apiChar[1], apiChar[2], apiChar[3],
// Call eax
0xFF, 0xD0,
// Pop all register
0x61,
// Pop all flags
0x9D,
// Ret
0xC3
};
*shellcodeSize = 22;
*shellcode = static_cast<unsigned char*>(malloc(22));
memcpy(*shellcode, sc, 22);
}
bool openFileDialog(std::string& selectedPath) {
OPENFILENAME ofn;
char fileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = nullptr;
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
// Updated filter to support both CHD and M3U
ofn.lpstrFilter = "Disc Images (*.chd;*.m3u)\0*.chd;*.m3u\0CHD Files (*.chd)\0*.chd\0M3U Playlists (*.m3u)\0*.m3u\0All Files (*.*)\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrTitle = "Select Sega Saturn disc image or M3U playlist";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileName(&ofn)) {
selectedPath = fileName;
return true;
}
return false;
}
void launchSSF(const std::string& imagePath) {
unsigned char* shellcode;
int shellcodeLen;
LPVOID remote_dllStringPtr;
LPVOID remote_shellcodePtr;
CONTEXT ctx;
// Get the Full DLL Path for our injection
GetFullPathName("ssf_patch.dll", 4096, inject_dll_path, nullptr);
// Create Process SUSPENDED
PROCESS_INFORMATION pi;
STARTUPINFOA Startup;
// Build command line with CHD/M3U path if provided
// SSF.exe just needs the path - the DLL will detect if it's M3U or CHD
std::string cmd_line;
if (!imagePath.empty()) {
cmd_line = "SSF.exe \"" + imagePath + "\"";
} else {
cmd_line = "SSF.exe";
}
ZeroMemory(&Startup, sizeof(Startup));
ZeroMemory(&pi, sizeof(pi));
GetFullPathName("SSF.exe", 4096, full_exe_path, nullptr);
// CreateProcessA needs writable buffer
std::vector<char> cmd_buffer(cmd_line.begin(), cmd_line.end());
cmd_buffer.push_back('\0');
if (!CreateProcessA(full_exe_path, cmd_buffer.data(), nullptr, nullptr, FALSE,
CREATE_SUSPENDED, nullptr, nullptr, &Startup, &pi)) {
MessageBox(nullptr, "Failed to launch SSF.exe\nMake sure SSFHelper.exe is in the same folder as SSF.exe",
"Error", MB_OK | MB_ICONERROR);
return;
}
remote_dllStringPtr = VirtualAllocEx(pi.hProcess, nullptr, strlen(inject_dll_path) + 1,
MEM_COMMIT, PAGE_READWRITE);
ctx.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(pi.hThread, &ctx);
createShellcode(ctx.Eip, reinterpret_cast<int>(remote_dllStringPtr), &shellcode, &shellcodeLen);
// Allocate Memory for Shellcode
remote_shellcodePtr = VirtualAllocEx(pi.hProcess, nullptr, shellcodeLen,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, remote_dllStringPtr, inject_dll_path, strlen(inject_dll_path) + 1, nullptr);
WriteProcessMemory(pi.hProcess, remote_shellcodePtr, shellcode, shellcodeLen, nullptr);
// Set EIP To Shellcode
ctx.Eip = reinterpret_cast<DWORD>(remote_shellcodePtr);
ctx.ContextFlags = CONTEXT_CONTROL;
SetThreadContext(pi.hThread, &ctx);
ResumeThread(pi.hThread);
Sleep(8000);
VirtualFreeEx(pi.hProcess, remote_dllStringPtr, strlen(inject_dll_path) + 1, MEM_DECOMMIT);
VirtualFreeEx(pi.hProcess, remote_shellcodePtr, shellcodeLen, MEM_DECOMMIT);
free(shellcode);
}
int main(int argc, char* argv[]) {
// Check if we have command line arguments (file path passed)
if (argc > 1) {
// Running from command line - keep console for debug output
printf("Launching SSF with: %s\n", argv[1]);
launchSSF(argv[1]);
} else {
// No arguments - show file picker (no console)
if (openFileDialog(chd_file_path)) {
launchSSF(chd_file_path);
}
}
return 0;
}