-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for running xochitl using the client. #29
Changes from 10 commits
67fa307
fdf65d1
6dff567
cbff4d0
303068a
a87ef55
e5ae655
bd09f2d
fc79ae5
70a0a98
9a5e21d
89b9136
b1f4e7e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,24 +10,38 @@ | |
#include <string> | ||
#include <unistd.h> | ||
|
||
#include <QByteArray> | ||
|
||
#include "../shared/ipc.cpp" | ||
#include "../shared/signature.cpp" | ||
|
||
#include "frida/frida-gum.h" | ||
|
||
#define FB_ID "mxcfb" | ||
|
||
#ifndef _GNU_SOURCE | ||
#define _GNU_SOURCE | ||
#endif | ||
|
||
using namespace std; | ||
int msg_q_id = 0x2257c; | ||
swtfb::ipc::Queue MSGQ(msg_q_id); | ||
|
||
uint16_t *SHARED_BUF; | ||
|
||
const int BYTES_PER_PIXEL = sizeof(uint16_t); | ||
|
||
bool IN_XOCHITL = false; | ||
|
||
extern "C" { | ||
struct stat; | ||
|
||
// QImage(width, height, format) | ||
static void (*qImageCtor)(void *that, int x, int y, int f) = 0; | ||
// QImage(uchar*, width, height, bytesperline, format) | ||
static void (*qImageCtorWithBuffer)(void *that, uint8_t *, int32_t x, int32_t y, | ||
int32_t bytes, int format, void (*)(void *), | ||
void *) = 0; | ||
|
||
static void _libhook_init() __attribute__((constructor)); | ||
static void _libhook_init() { | ||
std::ios_base::Init i; | ||
|
@@ -41,9 +55,30 @@ static void _libhook_init() { | |
} else { | ||
setenv("RM2FB_ACTIVE", "1", true); | ||
} | ||
|
||
qImageCtor = (void (*)(void *, int, int, int))dlsym( | ||
RTLD_NEXT, "_ZN6QImageC1EiiNS_6FormatE"); | ||
qImageCtorWithBuffer = (void (*)( | ||
void *, uint8_t *, int32_t, int32_t, int32_t, int, void (*)(void *), | ||
void *))dlsym(RTLD_NEXT, "_ZN6QImageC1EPhiiiNS_6FormatEPFvPvES2_"); | ||
|
||
SHARED_BUF = swtfb::ipc::get_shared_buffer(); | ||
} | ||
|
||
bool FIRST_ALLOC = true; | ||
void _ZN6QImageC1EiiNS_6FormatE(void *that, int x, int y, int f) { | ||
if (IN_XOCHITL && x == swtfb::WIDTH && y == swtfb::HEIGHT && FIRST_ALLOC) { | ||
fprintf(stderr, "REPLACING THE IMAGE with shared memory\n"); | ||
|
||
FIRST_ALLOC = false; | ||
qImageCtorWithBuffer(that, (uint8_t *)SHARED_BUF, swtfb::WIDTH, | ||
swtfb::HEIGHT, swtfb::WIDTH * BYTES_PER_PIXEL, f, | ||
nullptr, nullptr); | ||
return; | ||
} | ||
qImageCtor(that, x, y, f); | ||
} | ||
|
||
int open64(const char *pathname, int flags, mode_t mode = 0) { | ||
static int (*func_open)(const char *, int, mode_t) = NULL; | ||
|
||
|
@@ -53,7 +88,7 @@ int open64(const char *pathname, int flags, mode_t mode = 0) { | |
|
||
auto r = func_open(pathname, flags, mode); | ||
if (not IN_XOCHITL) { | ||
if (pathname == string("/dev/fb0")) { | ||
if (pathname == std::string("/dev/fb0")) { | ||
return swtfb::ipc::SWTFB_FD; | ||
} | ||
} | ||
|
@@ -70,7 +105,7 @@ int open(const char *pathname, int flags, mode_t mode = 0) { | |
|
||
auto r = func_open(pathname, flags, mode); | ||
if (not IN_XOCHITL) { | ||
if (pathname == string("/dev/fb0")) { | ||
if (pathname == std::string("/dev/fb0")) { | ||
return swtfb::ipc::SWTFB_FD; | ||
} | ||
} | ||
|
@@ -92,7 +127,9 @@ int ioctl(int fd, unsigned long request, char *ptr) { | |
|
||
return 0; | ||
} else if (request == MXCFB_WAIT_FOR_UPDATE_COMPLETE) { | ||
|
||
#ifdef DEBUG | ||
std::cerr << "CLIENT: sync" << std::endl; | ||
#endif | ||
return 0; | ||
} | ||
|
||
|
@@ -133,13 +170,131 @@ int ioctl(int fd, unsigned long request, char *ptr) { | |
return func_ioctl(fd, request, ptr); | ||
} | ||
|
||
static const auto touchArgs = QByteArray("rotate=180:invertx"); | ||
|
||
bool _Z7qputenvPKcRK10QByteArray(const char *name, const QByteArray &val) { | ||
static auto orig_fn = (bool (*)(const char *, const QByteArray &))dlsym( | ||
RTLD_NEXT, "_Z7qputenvPKcRK10QByteArray"); | ||
|
||
if (strcmp(name, "QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS") == 0) { | ||
return orig_fn(name, touchArgs); | ||
} | ||
|
||
return orig_fn(name, val); | ||
} | ||
|
||
void (*old_update)(void *, int, int, int, int, int, int) = 0; | ||
int (*old_create_threads)(const char *, void *) = 0; | ||
int (*old_wait)(void) = 0; | ||
int (*old_shutdown)(void) = 0; | ||
|
||
void new_update(void *instance, int x1, int y1, int x2, int y2, int waveform, | ||
int flags) { | ||
#ifdef DEBUG | ||
std::cerr << "UPDATE HOOK CALLED" << std::endl; | ||
std::cerr << "x " << x1 << " " << x2 << std::endl; | ||
std::cerr << "y " << y1 << " " << y2 << std::endl; | ||
std::cerr << "wav " << waveform << " flags " << flags << std::endl; | ||
#endif | ||
|
||
swtfb::xochitl_data data; | ||
data.x1 = x1; | ||
data.x2 = x2; | ||
data.y1 = y1; | ||
data.y2 = y2; | ||
data.waveform = waveform; | ||
data.flags = flags; | ||
MSGQ.send(data); | ||
} | ||
|
||
int new_create_threads(const char *path, void *buf) { | ||
std::cerr << "create threads called" << std::endl; | ||
return 0; | ||
} | ||
|
||
int new_wait(void) { | ||
std::cerr << "wait clear func called" << std::endl; | ||
return 0; | ||
} | ||
|
||
int new_shutdown(void) { | ||
std::cerr << "shutdown called" << std::endl; | ||
return 0; | ||
} | ||
|
||
GumInterceptor *interceptor; | ||
|
||
int __libc_start_main(int (*_main)(int, char **, char **), int argc, | ||
char **argv, int (*init)(int, char **, char **), | ||
void (*fini)(void), void (*rtld_fini)(void), | ||
void *stack_end) { | ||
|
||
if (string(argv[0]).find("xochitl") != string::npos) { | ||
if (std::string(argv[0]).find("xochitl") != std::string::npos) { | ||
raisjn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
IN_XOCHITL = true; | ||
|
||
auto *update_fn = | ||
swtfb::locate_signature(argv[0], "\x54\x40\x8d\xe2\x10\x50\x8d\xe2", 8); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the signature isn't found, it should point people to issue #18 |
||
if (update_fn == nullptr) { | ||
std::cerr << "Unable to find update fn" << std::endl; | ||
return -1; | ||
} | ||
update_fn -= 12; | ||
|
||
auto *create_threads_fn = swtfb::locate_signature( | ||
argv[0], "\x00\x40\xa0\xe1\x10\x52\x9f\xe5\x6b\x0d\xa0\xe3", 12); | ||
if (create_threads_fn == nullptr) { | ||
std::cerr << "Unable to find update fn" << std::endl; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bad copy/paste here |
||
return -1; | ||
} | ||
|
||
auto *wait_fn = | ||
swtfb::locate_signature(argv[0], "\x01\x30\xa0\xe3\x30\x40\x9f\xe5", 8); | ||
if (wait_fn == nullptr) { | ||
std::cerr << "Unable to find update fn" << std::endl; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here |
||
return -1; | ||
} | ||
|
||
auto *shutdown_fn = | ||
swtfb::locate_signature(argv[0], "\x01\x50\xa0\xe3\x44\x40\x9f\xe5", 8); | ||
if (shutdown_fn == nullptr) { | ||
std::cerr << "Unable to find update fn" << std::endl; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here |
||
return -1; | ||
} | ||
|
||
std::cerr << "Update fn address: " << std::hex << (void *)update_fn | ||
<< "\nCreate th address: " << (void *)create_threads_fn | ||
<< "\nWait for th address: " << (void *)wait_fn | ||
<< "\nshutdown address: " << (void *)shutdown_fn << std::dec | ||
<< std::endl; | ||
|
||
old_update = (decltype(old_update))update_fn; | ||
old_create_threads = (decltype(old_create_threads))create_threads_fn; | ||
old_wait = (decltype(old_wait))wait_fn; | ||
old_shutdown = (decltype(old_shutdown))shutdown_fn; | ||
|
||
gum_init_embedded(); | ||
interceptor = gum_interceptor_obtain(); | ||
|
||
if (gum_interceptor_replace(interceptor, update_fn, (void *)new_update, | ||
nullptr) != GUM_REPLACE_OK) { | ||
std::cerr << "replace update fnerror" << std::endl; | ||
} | ||
|
||
if (gum_interceptor_replace(interceptor, create_threads_fn, | ||
(void *)new_create_threads, | ||
nullptr) != GUM_REPLACE_OK) { | ||
std::cerr << "replace create threads error" << std::endl; | ||
} | ||
|
||
if (gum_interceptor_replace(interceptor, wait_fn, (void *)new_wait, | ||
nullptr) != GUM_REPLACE_OK) { | ||
std::cerr << "replace wait clear error" << std::endl; | ||
} | ||
|
||
if (gum_interceptor_replace(interceptor, shutdown_fn, (void *)new_shutdown, | ||
nullptr) != GUM_REPLACE_OK) { | ||
std::cerr << "replace shutdown error" << std::endl; | ||
} | ||
} | ||
|
||
typeof(&__libc_start_main) func_main = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice