Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "third_party/subhook"]
path = third_party/subhook
url = https://github.com/Zeex/subhook.git
url = https://github.com/Dasharo/subhook.git
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10)

project (DarkTanos)

set(API_VERSION 7)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
Expand Down
6 changes: 6 additions & 0 deletions client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ find_package(JNI REQUIRED)

include_directories(${PROJECT_NAME} PRIVATE ${JNI_INCLUDE_DIRS})

add_definitions(-DAPI_VERSION=${API_VERSION})

add_library(${PROJECT_NAME} SHARED
eu_darkbot_api_DarkTanos.cpp
bot_client.cpp
proc_util.cpp
sock_ipc.cpp
)

find_package(X11 REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${X11_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} PRIVATE ${X11_LIBRARIES})

target_compile_options(${PROJECT_NAME} PRIVATE -std=c++17)
281 changes: 268 additions & 13 deletions client/bot_client.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include "bot_client.h"
#include <cstring>
#include <thread>
#include <chrono>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <cstdio>

#include "utils.h"
#include "proc_util.h"
Expand All @@ -16,9 +14,251 @@
#include <sys/sem.h>
#include <sys/wait.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>


#define MEM_SIZE 1024

namespace
{
Window browser_window = 0;

bool get_window_pid(Display *display, Window window, pid_t &pid)
{
Atom atom_pid = XInternAtom(display, "_NET_WM_PID", True);
if (atom_pid == None)
{
return false;
}

Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0;
unsigned long bytes_after = 0;
unsigned char *prop = nullptr;

int status = XGetWindowProperty(
display,
window,
atom_pid,
0,
1,
False,
XA_CARDINAL,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
&prop);

if (status != Success || !prop || nitems == 0)
{
if (prop)
{
XFree(prop);
}
return false;
}

pid = static_cast<pid_t>(*reinterpret_cast<unsigned long *>(prop));
XFree(prop);
return true;
}

bool is_browser_window_pid(pid_t owner_pid, pid_t browser_pid)
{
return owner_pid == browser_pid || ProcUtil::IsChildOf(owner_pid, browser_pid);
}

bool x11_window_control_available()
{
const char *display = std::getenv("DISPLAY");
return display && *display;
}

bool try_get_window_attrs(Display *display, Window window)
{
XWindowAttributes attrs;
if (XGetWindowAttributes(display, window, &attrs) != 0)
{
return true;
}

XSync(display, False);
return XGetWindowAttributes(display, window, &attrs) != 0;
}

Window find_toplevel_root_child(Display *display, Window root, Window window)
{
if (!window)
{
return 0;
}

Window current = window;
while (current)
{
Window root_return = 0;
Window parent_return = 0;
Window *children = nullptr;
unsigned int nchildren = 0;

if (!XQueryTree(display, current, &root_return, &parent_return, &children, &nchildren))
{
return current;
}

if (children)
{
XFree(children);
}

if (parent_return == 0 || parent_return == root)
{
return current;
}

current = parent_return;
}

return window;
}

Window find_browser_owned_descendant_recursive(Display *display, Window root, pid_t browser_pid)
{
if (!root)
{
return 0;
}

pid_t owner_pid = -1;
if (get_window_pid(display, root, owner_pid) && is_browser_window_pid(owner_pid, browser_pid))
{
return root;
}

Window root_return = 0;
Window parent_return = 0;
Window *children = nullptr;
unsigned int nchildren = 0;

if (!XQueryTree(display, root, &root_return, &parent_return, &children, &nchildren))
{
return 0;
}

Window found = 0;
for (unsigned int i = 0; i < nchildren && !found; i++)
{
found = find_browser_owned_descendant_recursive(display, children[i], browser_pid);
}

if (children)
{
XFree(children);
}
return found;
}

Window find_browser_client_window(Display *display, pid_t browser_pid)
{
Window root = DefaultRootWindow(display);
Atom atom_client_list = XInternAtom(display, "_NET_CLIENT_LIST", True);
if (atom_client_list != None)
{
Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0;
unsigned long bytes_after = 0;
unsigned char *prop = nullptr;

int status = XGetWindowProperty(
display,
root,
atom_client_list,
0,
4096,
False,
XA_WINDOW,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
&prop);

if (status == Success && prop && actual_type == XA_WINDOW)
{
Window *windows = reinterpret_cast<Window *>(prop);
Window child_fallback = 0;
for (unsigned long i = 0; i < nitems; i++)
{
pid_t owner_pid = -1;
if (!get_window_pid(display, windows[i], owner_pid))
{
continue;
}

if (owner_pid == browser_pid)
{
XFree(prop);
return windows[i];
}

if (!child_fallback && ProcUtil::IsChildOf(owner_pid, browser_pid))
{
child_fallback = windows[i];
}
}

XFree(prop);
if (child_fallback)
{
return child_fallback;
}
}
else if (prop)
{
XFree(prop);
}
}

Window any_owned = find_browser_owned_descendant_recursive(display, root, browser_pid);
if (!any_owned)
{
return 0;
}

return find_toplevel_root_child(display, root, any_owned);
}

void toggle_browser_visibility(pid_t browser_pid, bool visible)
{
Display *display = XOpenDisplay(nullptr);
if (!display)
{
return; // Failed to open display
}

if (!browser_window || !try_get_window_attrs(display, browser_window))
{
browser_window = find_browser_client_window(display, browser_pid);
}

if (!browser_window)
{
XCloseDisplay(display);
return; // Failed to find browser window
}

// Show or hide the browser window
visible ? XMapWindow(display, browser_window) : XUnmapWindow(display, browser_window);

XFlush(display);
XCloseDisplay(display);
}
}


enum class MessageType
{
Expand Down Expand Up @@ -125,6 +365,16 @@ BotClient::BotClient() :
{
}

void BotClient::ToggleBrowserVisibility(bool visible)
{
if (m_flash_pid == -1 || !x11_window_control_available())
{
return;
}

toggle_browser_visibility(m_browser_pid, visible);
}

BotClient::~BotClient()
{
if (m_browser_pid > 0)
Expand Down Expand Up @@ -177,7 +427,17 @@ void BotClient::LaunchBrowser()
sid.replace(0, 6, "");
}

execle(fpath, fpath, "--sid", sid.c_str(), "--url", url.c_str(), "--launch", NULL, envp.data());
execle(
fpath,
fpath,
"--sid", sid.c_str(),
"--url", url.c_str(),
"--launch",
"--ozone-platform=x11",
"--disable-background-timer-throttling",
"--disable-renderer-backgrounding",
NULL,
envp.data());
break;
}
default:
Expand Down Expand Up @@ -249,7 +509,6 @@ void BotClient::reset()
m_flash_pid = -1;
m_flash_sem = -1;
m_flash_shmid = -1;
m_flash_pid = -1;
}

// Not a great name since it has side-effects like refreshgin or restarting the browser
Expand Down Expand Up @@ -285,12 +544,10 @@ void BotClient::SendFlashCommand(Message *message, Message *response)
return;
}

if ((m_flash_shmid = shmget(m_flash_pid, MEM_SIZE, IPC_CREAT | 0666)) < 0)
{
if ((m_flash_shmid = shmget(m_flash_pid, MEM_SIZE, IPC_CREAT | 0666)) < 0)
{
fprintf(stderr, "[SendFlashCommand] Failed to get shared memory\n");
return;
}
fprintf(stderr, "[SendFlashCommand] Failed to get shared memory\n");
return;
}

if (!m_shared_mem_flash || m_shared_mem_flash == (void *)-1)
Expand Down Expand Up @@ -319,7 +576,6 @@ void BotClient::SendFlashCommand(Message *message, Message *response)
sembuf sop[2] { { 0, -1, 0 }, { 1, 0, 0 } };

// Notify
sop[0] = { 0, -1, 0 };
if (semtimedop(m_flash_sem, &sop[0], 1, &timeout) == -1)
{
if (errno == EAGAIN)
Expand All @@ -332,7 +588,6 @@ void BotClient::SendFlashCommand(Message *message, Message *response)
}

// Wait
sop[1] = { 1, 0, 0 };
if (semtimedop(m_flash_sem, &sop[1], 1, &timeout) == -1)
{
if (errno == EAGAIN)
Expand Down
1 change: 1 addition & 0 deletions client/bot_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class BotClient
bool IsValid();

void SendBrowserCommand(const std::string &&s, int sync);
void ToggleBrowserVisibility(bool visible);

void SendFlashCommand(Message *message, Message *response = nullptr);

Expand Down
Loading