2024-02-07 20:59:24 +08:00
|
|
|
|
|
|
|
|
|
#include <CommCtrl.h>
|
|
|
|
|
#include <TlHelp32.h>
|
|
|
|
|
#include<stdio.h>
|
2024-03-27 16:36:14 +08:00
|
|
|
|
#include<thread>
|
2024-02-09 09:25:26 +08:00
|
|
|
|
#include<fstream>
|
2024-02-07 20:59:24 +08:00
|
|
|
|
#include"host.h"
|
|
|
|
|
#include"hookcode.h"
|
|
|
|
|
#include"textthread.h"
|
|
|
|
|
#include"LunaHost.h"
|
|
|
|
|
#include"Lang/Lang.h"
|
2024-03-28 19:24:07 +08:00
|
|
|
|
auto gmf=[&](DWORD processId)->std::optional<std::wstring>{
|
|
|
|
|
//见鬼了,GetModuleFileName找不到标识符
|
|
|
|
|
std::vector<wchar_t> buffer(MAX_PATH);
|
|
|
|
|
if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))
|
|
|
|
|
if (GetModuleFileNameExW(process, 0, buffer.data(), MAX_PATH)) return buffer.data();
|
|
|
|
|
return {};
|
|
|
|
|
};
|
2024-02-07 20:59:24 +08:00
|
|
|
|
void LunaHost::toclipboard(std::wstring& sentence){
|
|
|
|
|
|
|
|
|
|
for (int loop = 0; loop < 10; loop++) {
|
|
|
|
|
if (OpenClipboard(winId)) {
|
|
|
|
|
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (sentence.size() + 2) * sizeof(wchar_t));
|
|
|
|
|
memcpy(GlobalLock(hMem), sentence.c_str(), (sentence.size() + 2) * sizeof(wchar_t));
|
|
|
|
|
EmptyClipboard();
|
|
|
|
|
SetClipboardData(CF_UNICODETEXT, hMem);
|
|
|
|
|
GlobalUnlock(hMem);
|
|
|
|
|
CloseClipboard();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void LunaHost::on_close(){
|
2024-03-27 14:23:36 +08:00
|
|
|
|
savesettings();
|
2024-02-09 09:25:26 +08:00
|
|
|
|
delete configs;
|
2024-02-07 20:59:24 +08:00
|
|
|
|
for(auto pid:attachedprocess){
|
|
|
|
|
Host::DetachProcess(pid);
|
|
|
|
|
}
|
2024-02-10 12:43:51 +08:00
|
|
|
|
if(attachedprocess.size())
|
2024-03-27 16:36:14 +08:00
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
2024-02-07 20:59:24 +08:00
|
|
|
|
}
|
2024-03-28 11:01:44 +08:00
|
|
|
|
|
2024-03-27 14:23:36 +08:00
|
|
|
|
void LunaHost::savesettings()
|
|
|
|
|
{
|
|
|
|
|
configs->set("ToClipboard",check_toclipboard);
|
|
|
|
|
configs->set("AutoAttach",autoattach);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
configs->set("AutoAttach_SavedOnly",autoattach_savedonly);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
configs->set("flushDelay",TextThread::flushDelay);
|
|
|
|
|
configs->set("filterRepetition",TextThread::filterRepetition);
|
|
|
|
|
configs->set("maxBufferSize",TextThread::maxBufferSize);
|
2024-03-28 00:31:53 +08:00
|
|
|
|
configs->set("maxHistorySize",TextThread::maxHistorySize);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
configs->set("defaultCodepage",Host::defaultCodepage);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
configs->set("autoattachexes",autoattachexes);
|
|
|
|
|
configs->set("savedhookcontext",savedhookcontext);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
}
|
|
|
|
|
void LunaHost::loadsettings(){
|
|
|
|
|
check_toclipboard=configs->get("ToClipboard",false);
|
|
|
|
|
autoattach=configs->get("AutoAttach",false);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
autoattach_savedonly=configs->get("AutoAttach_SavedOnly",true);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
TextThread::flushDelay=configs->get("flushDelay",TextThread::flushDelay);
|
|
|
|
|
TextThread::filterRepetition=configs->get("filterRepetition",TextThread::filterRepetition);
|
|
|
|
|
TextThread::maxBufferSize=configs->get("maxBufferSize",TextThread::maxBufferSize);
|
2024-03-28 00:31:53 +08:00
|
|
|
|
TextThread::maxHistorySize=configs->get("maxHistorySize",TextThread::maxHistorySize);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
Host::defaultCodepage=configs->get("defaultCodepage",Host::defaultCodepage);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
autoattachexes=configs->get("autoattachexes",std::set<std::string>{});
|
|
|
|
|
savedhookcontext=configs->get("savedhookcontext",decltype(savedhookcontext){});
|
2024-03-27 14:23:36 +08:00
|
|
|
|
}
|
2024-03-27 16:36:14 +08:00
|
|
|
|
|
|
|
|
|
std::unordered_map<std::wstring,std::vector<int>> getprocesslist();
|
|
|
|
|
void LunaHost::doautoattach()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if(autoattach==false&&autoattach_savedonly==false)return;
|
|
|
|
|
|
|
|
|
|
if(autoattachexes.empty())return;
|
|
|
|
|
|
|
|
|
|
for(auto [pexe,pids ]:getprocesslist())
|
|
|
|
|
{
|
|
|
|
|
auto&& u8procname=WideStringToString(pexe);
|
|
|
|
|
if(autoattachexes.find(u8procname)==autoattachexes.end())continue;
|
|
|
|
|
if(autoattach_savedonly && savedhookcontext.find(u8procname)==savedhookcontext.end())continue;
|
|
|
|
|
for(auto pid:pids){
|
|
|
|
|
if(userdetachedpids.find(pid)!=userdetachedpids.end())continue;
|
|
|
|
|
|
|
|
|
|
if(attachedprocess.find(pid)==attachedprocess.end())
|
|
|
|
|
Host::InjectProcess(pid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LunaHost::on_proc_connect(DWORD pid)
|
|
|
|
|
{
|
|
|
|
|
attachedprocess.insert(pid);
|
|
|
|
|
|
|
|
|
|
if(auto pexe=GetModuleFilename(pid))
|
|
|
|
|
{
|
|
|
|
|
autoattachexes.insert(WideStringToString(pexe.value()));
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-07 20:59:24 +08:00
|
|
|
|
LunaHost::LunaHost(){
|
2024-03-27 16:36:14 +08:00
|
|
|
|
|
|
|
|
|
configs=new confighelper;
|
2024-03-27 14:23:36 +08:00
|
|
|
|
loadsettings();
|
2024-03-27 16:36:14 +08:00
|
|
|
|
|
|
|
|
|
std::thread([&]{
|
|
|
|
|
while(1){
|
|
|
|
|
doautoattach();
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
|
|
|
|
}
|
|
|
|
|
}).detach();
|
|
|
|
|
|
2024-02-11 23:49:11 +08:00
|
|
|
|
setfont(25);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
settext(WndLunaHostGui);
|
2024-03-28 11:01:44 +08:00
|
|
|
|
btnshowsettionwindow=new button(this, BtnShowSettingWindow);
|
|
|
|
|
g_selectprocessbutton =new button(this,BtnSelectProcess) ;
|
2024-03-27 16:36:14 +08:00
|
|
|
|
|
|
|
|
|
// btnsavehook=new button(this,BtnSaveHook,10,10,10,10);
|
|
|
|
|
// btnsavehook->onclick=std::bind(&LunaHost::btnsavehookscallback,this);
|
2024-03-28 11:01:44 +08:00
|
|
|
|
btndetachall=new button(this,BtnDetach);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
btndetachall->onclick=[&](){
|
|
|
|
|
for(auto pid:attachedprocess){
|
|
|
|
|
Host::DetachProcess(pid);
|
|
|
|
|
userdetachedpids.insert(pid);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
g_hEdit_userhook = new lineedit(this);
|
|
|
|
|
btnplugin=new button(this,BtnPlugin);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
|
|
|
|
|
plugins=new Pluginmanager(this);
|
|
|
|
|
btnplugin->onclick=[&](){
|
|
|
|
|
if(pluginwindow==0) pluginwindow=new Pluginwindow(this,plugins);
|
|
|
|
|
pluginwindow->show();
|
2024-02-08 16:18:33 +08:00
|
|
|
|
};
|
2024-03-28 11:01:44 +08:00
|
|
|
|
g_hButton_insert = new button(this,BtnInsertUserHook) ;
|
2024-02-09 09:25:26 +08:00
|
|
|
|
btnshowsettionwindow->onclick=[&](){
|
|
|
|
|
if(settingwindow==0) settingwindow=new Settingwindow(this);
|
|
|
|
|
settingwindow->show();
|
|
|
|
|
};
|
2024-02-07 20:59:24 +08:00
|
|
|
|
g_selectprocessbutton->onclick=[&](){
|
|
|
|
|
if(_processlistwindow==0) _processlistwindow=new processlistwindow(this);
|
|
|
|
|
_processlistwindow->show();
|
|
|
|
|
};
|
|
|
|
|
g_hButton_insert->onclick=[&](){
|
|
|
|
|
auto hp = HookCode::Parse(std::move(g_hEdit_userhook->text()));
|
|
|
|
|
if(hp){
|
|
|
|
|
for(auto _:attachedprocess){
|
|
|
|
|
Host::InsertHook(_,hp.value());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
g_showtexts->appendtext(NotifyInvalidHookCode);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
g_hListBox_listtext = new listbox(this);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
g_hListBox_listtext->oncurrentchange=[&](int idx){
|
|
|
|
|
uint64_t handle = g_hListBox_listtext->getdata(idx);
|
|
|
|
|
std::wstring get;
|
|
|
|
|
for(auto& _:savetext.at(handle)){
|
|
|
|
|
get+=_;
|
|
|
|
|
get+=L"\r\n";
|
|
|
|
|
}
|
|
|
|
|
currentselect=handle;
|
|
|
|
|
g_showtexts->settext(get);
|
|
|
|
|
g_showtexts->scrolltoend();
|
|
|
|
|
};
|
2024-03-29 18:07:15 +08:00
|
|
|
|
g_hListBox_listtext->on_menu=[&]()->maybehavemenu{
|
|
|
|
|
auto handle = g_hListBox_listtext->getdata(g_hListBox_listtext->currentidx());
|
|
|
|
|
auto tt=Host::GetThread(handle);
|
|
|
|
|
if(!tt)return {};
|
|
|
|
|
Menu menu;
|
2024-03-29 21:46:24 +08:00
|
|
|
|
menu.add(MenuCopyHookCode,[&,tt](){toclipboard(std::wstring(tt->hp.hookcode));});
|
2024-03-29 18:07:15 +08:00
|
|
|
|
menu.add_sep();
|
2024-03-29 21:46:24 +08:00
|
|
|
|
menu.add(MenuRemoveHook,[&,tt](){Host::RemoveHook(tt->tp.processId,tt->tp.addr);});
|
|
|
|
|
menu.add(MenuDetachProcess,[&,tt](){
|
2024-03-29 18:07:15 +08:00
|
|
|
|
|
2024-03-29 15:07:43 +08:00
|
|
|
|
Host::DetachProcess(tt->tp.processId);
|
2024-03-29 18:07:15 +08:00
|
|
|
|
userdetachedpids.insert(tt->tp.processId);
|
|
|
|
|
});
|
|
|
|
|
menu.add_sep();
|
2024-03-29 21:46:24 +08:00
|
|
|
|
menu.add(MenuRemeberSelect,[&,tt](){
|
2024-03-29 15:07:43 +08:00
|
|
|
|
if(auto pexe=gmf(tt->tp.processId))
|
|
|
|
|
savedhookcontext[WideStringToString(pexe.value())]={
|
|
|
|
|
{"hookcode",WideStringToString(tt->hp.hookcode)},
|
|
|
|
|
{"ctx1",tt->tp.ctx},
|
|
|
|
|
{"ctx2",tt->tp.ctx2},
|
|
|
|
|
};
|
2024-03-29 18:07:15 +08:00
|
|
|
|
});
|
2024-03-29 21:46:24 +08:00
|
|
|
|
menu.add(MenuForgetSelect,[&,tt](){
|
2024-03-29 18:07:15 +08:00
|
|
|
|
if(auto pexe=gmf(tt->tp.processId))
|
|
|
|
|
savedhookcontext.erase(WideStringToString(pexe.value()));
|
|
|
|
|
});
|
|
|
|
|
return menu;
|
|
|
|
|
};
|
2024-03-29 15:07:43 +08:00
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
g_showtexts = new multilineedit(this);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
g_showtexts->setreadonly(true);
|
2024-03-28 19:24:07 +08:00
|
|
|
|
|
|
|
|
|
btnsearchhooks=new button(this,BtnSearchHook);
|
|
|
|
|
btnsearchhooks->onclick=[&](){
|
|
|
|
|
if(hooksearchwindow==0) hooksearchwindow=new Hooksearchwindow(this);
|
|
|
|
|
hooksearchwindow->show();
|
|
|
|
|
};
|
|
|
|
|
|
2024-02-07 20:59:24 +08:00
|
|
|
|
Host::Start(
|
2024-03-27 16:36:14 +08:00
|
|
|
|
std::bind(&LunaHost::on_proc_connect,this,std::placeholders::_1),
|
2024-02-07 20:59:24 +08:00
|
|
|
|
[&](DWORD pid) {
|
2024-03-27 16:36:14 +08:00
|
|
|
|
attachedprocess.erase(pid);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
},
|
2024-02-08 16:18:33 +08:00
|
|
|
|
std::bind(&LunaHost::on_thread_create,this,std::placeholders::_1),
|
|
|
|
|
std::bind(&LunaHost::on_thread_delete,this,std::placeholders::_1),
|
|
|
|
|
std::bind(&LunaHost::on_text_recv,this,std::placeholders::_1,std::placeholders::_2)
|
2024-02-07 20:59:24 +08:00
|
|
|
|
);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
mainlayout=new gridlayout();
|
|
|
|
|
mainlayout->addcontrol(g_selectprocessbutton,0,0);
|
|
|
|
|
mainlayout->addcontrol(btndetachall,0,1);
|
|
|
|
|
mainlayout->addcontrol(btnshowsettionwindow,0,2);
|
|
|
|
|
mainlayout->addcontrol(btnplugin,0,3);
|
2024-03-28 19:24:07 +08:00
|
|
|
|
mainlayout->addcontrol(g_hEdit_userhook,1,0,1,2);
|
|
|
|
|
mainlayout->addcontrol(g_hButton_insert,1,2);
|
|
|
|
|
mainlayout->addcontrol(btnsearchhooks,1,3);
|
2024-03-28 11:01:44 +08:00
|
|
|
|
|
|
|
|
|
mainlayout->addcontrol(g_hListBox_listtext,2,0,1,4);
|
|
|
|
|
mainlayout->addcontrol(g_showtexts,3,0,1,4);
|
|
|
|
|
|
|
|
|
|
mainlayout->setfixedheigth(0,30);
|
|
|
|
|
mainlayout->setfixedheigth(1,30);
|
|
|
|
|
setlayout(mainlayout);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
setcentral(1200,800);
|
2024-02-08 16:18:33 +08:00
|
|
|
|
}
|
2024-03-27 16:36:14 +08:00
|
|
|
|
void LunaHost::on_text_recv_checkissaved(TextThread& thread)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if(onceautoselectthread.find(thread.handle)!=onceautoselectthread.end())return;
|
|
|
|
|
|
|
|
|
|
onceautoselectthread.insert(thread.handle);
|
|
|
|
|
|
|
|
|
|
if(auto exe=GetModuleFilename(thread.tp.processId))
|
|
|
|
|
{
|
|
|
|
|
auto exea=WideStringToString(exe.value());
|
|
|
|
|
if(savedhookcontext.find(exea)==savedhookcontext.end())return;
|
|
|
|
|
|
|
|
|
|
std::string hc= savedhookcontext[exea]["hookcode"];
|
|
|
|
|
uint64_t ctx1=savedhookcontext[exea]["ctx1"];
|
|
|
|
|
uint64_t ctx2=savedhookcontext[exea]["ctx2"];
|
|
|
|
|
if(((ctx1&0xffff)==(thread.tp.ctx&0xffff) )&& (ctx2==thread.tp.ctx2) && (hc==WideStringToString(thread.hp.hookcode)))
|
|
|
|
|
{
|
|
|
|
|
for(int i=0;i<g_hListBox_listtext->count();i++)
|
|
|
|
|
{
|
|
|
|
|
auto handle=g_hListBox_listtext->getdata(i);
|
|
|
|
|
if(handle==thread.handle)
|
|
|
|
|
{
|
|
|
|
|
g_hListBox_listtext->setcurrent(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2024-02-08 16:18:33 +08:00
|
|
|
|
|
2024-03-27 16:36:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2024-02-08 16:18:33 +08:00
|
|
|
|
bool LunaHost::on_text_recv(TextThread& thread, std::wstring& output){
|
|
|
|
|
std::lock_guard _(settextmutex);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
on_text_recv_checkissaved(thread);
|
2024-02-08 19:12:20 +08:00
|
|
|
|
if(!plugins->dispatch(thread,output))return false;
|
2024-02-09 09:40:07 +08:00
|
|
|
|
strReplace(output,L"\n",L"\r\n");
|
|
|
|
|
savetext.at(thread.handle).push_back(output);
|
2024-02-08 16:18:33 +08:00
|
|
|
|
if(currentselect==thread.handle){
|
|
|
|
|
g_showtexts->scrolltoend();
|
2024-02-09 09:40:07 +08:00
|
|
|
|
g_showtexts->appendtext(output);
|
2024-02-08 16:18:33 +08:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
void LunaHost::on_thread_create(TextThread& thread){
|
|
|
|
|
wchar_t buff[65535];
|
|
|
|
|
swprintf_s(buff,L"[%I64X:%I32X:%I64X:%I64X:%I64X:%s:%s]",
|
|
|
|
|
thread.handle,
|
|
|
|
|
thread.tp.processId,
|
|
|
|
|
thread.tp.addr,
|
|
|
|
|
thread.tp.ctx,
|
|
|
|
|
thread.tp.ctx2,
|
|
|
|
|
thread.name.c_str(),
|
|
|
|
|
thread.hp.hookcode
|
|
|
|
|
);
|
|
|
|
|
savetext.insert({thread.handle,{}});
|
|
|
|
|
int index=g_hListBox_listtext->additem(buff);
|
|
|
|
|
g_hListBox_listtext->setdata(index,thread.handle);
|
|
|
|
|
}
|
|
|
|
|
void LunaHost::on_thread_delete(TextThread& thread){
|
|
|
|
|
int count = g_hListBox_listtext->count();
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
uint64_t handle = g_hListBox_listtext->getdata(i);
|
|
|
|
|
|
|
|
|
|
if (handle== thread.handle) {
|
|
|
|
|
g_hListBox_listtext->deleteitem(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-09 09:25:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
|
2024-03-27 14:23:36 +08:00
|
|
|
|
int height=30;int curry=10;int space=10;
|
2024-03-28 00:31:53 +08:00
|
|
|
|
int labelwidth=300;int spinwidth=200;
|
2024-03-28 19:24:07 +08:00
|
|
|
|
g_timeout = new spinbox(this,TextThread::flushDelay) ;
|
2024-03-28 11:01:44 +08:00
|
|
|
|
|
|
|
|
|
|
2024-03-28 19:24:07 +08:00
|
|
|
|
g_codepage = new spinbox(this,Host::defaultCodepage) ;
|
2024-03-27 14:23:36 +08:00
|
|
|
|
|
|
|
|
|
|
2024-03-28 19:24:07 +08:00
|
|
|
|
spinmaxbuffsize = new spinbox(this,TextThread::maxBufferSize);
|
2024-03-28 11:01:44 +08:00
|
|
|
|
;curry+=height+space;
|
2024-03-27 14:23:36 +08:00
|
|
|
|
|
|
|
|
|
spinmaxbuffsize->onvaluechange=[=](int v){
|
2024-03-27 16:36:14 +08:00
|
|
|
|
TextThread::maxBufferSize=v;
|
2024-03-27 14:23:36 +08:00
|
|
|
|
};
|
2024-03-28 00:31:53 +08:00
|
|
|
|
|
2024-03-28 19:24:07 +08:00
|
|
|
|
spinmaxhistsize = new spinbox(this,TextThread::maxHistorySize) ;
|
2024-03-28 11:01:44 +08:00
|
|
|
|
;curry+=height+space;
|
2024-03-28 00:31:53 +08:00
|
|
|
|
|
|
|
|
|
spinmaxhistsize->onvaluechange=[=](int v){
|
|
|
|
|
TextThread::maxHistorySize=v;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
ckbfilterrepeat=new checkbox(this,LblFilterRepeat);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
ckbfilterrepeat->onclick=[=](){
|
2024-03-27 14:23:36 +08:00
|
|
|
|
TextThread::filterRepetition=ckbfilterrepeat->ischecked();
|
2024-02-09 09:25:26 +08:00
|
|
|
|
};
|
2024-03-27 14:23:36 +08:00
|
|
|
|
ckbfilterrepeat->setcheck(TextThread::filterRepetition);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
g_check_clipboard =new checkbox(this,BtnToClipboard);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
g_check_clipboard->onclick=[=](){
|
2024-03-27 16:36:14 +08:00
|
|
|
|
host->check_toclipboard=g_check_clipboard->ischecked();
|
2024-02-09 09:59:49 +08:00
|
|
|
|
};
|
2024-03-27 14:23:36 +08:00
|
|
|
|
g_check_clipboard->setcheck(host->check_toclipboard);
|
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
autoattach =new checkbox(this,LblAutoAttach);
|
2024-03-27 14:23:36 +08:00
|
|
|
|
autoattach->onclick=[=](){
|
2024-03-27 16:36:14 +08:00
|
|
|
|
host->autoattach=autoattach->ischecked();
|
2024-03-27 14:23:36 +08:00
|
|
|
|
};
|
|
|
|
|
autoattach->setcheck(host->autoattach);
|
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
autoattach_so =new checkbox(this,LblAutoAttach_savedonly);
|
2024-03-27 16:36:14 +08:00
|
|
|
|
autoattach_so->onclick=[=](){
|
|
|
|
|
host->autoattach_savedonly=autoattach_so->ischecked();
|
|
|
|
|
};
|
|
|
|
|
autoattach_so->setcheck(host->autoattach_savedonly);
|
|
|
|
|
|
2024-03-27 14:23:36 +08:00
|
|
|
|
|
2024-03-28 11:01:44 +08:00
|
|
|
|
readonlycheck=new checkbox(this,BtnReadOnly);
|
2024-02-20 23:24:33 +08:00
|
|
|
|
readonlycheck->onclick=[=](){
|
2024-03-27 16:36:14 +08:00
|
|
|
|
host->g_showtexts->setreadonly(readonlycheck->ischecked());
|
2024-02-20 23:24:33 +08:00
|
|
|
|
};
|
2024-03-27 14:23:36 +08:00
|
|
|
|
readonlycheck->setcheck(true);
|
|
|
|
|
|
2024-02-09 19:38:12 +08:00
|
|
|
|
g_timeout->onvaluechange=[=](int v){
|
|
|
|
|
TextThread::flushDelay=v;
|
2024-02-09 09:25:26 +08:00
|
|
|
|
};
|
2024-03-28 19:24:07 +08:00
|
|
|
|
|
2024-02-09 19:38:12 +08:00
|
|
|
|
g_codepage->onvaluechange=[=](int v){
|
|
|
|
|
if(IsValidCodePage(v)){
|
|
|
|
|
Host::defaultCodepage= v;
|
2024-02-09 09:25:26 +08:00
|
|
|
|
}
|
2024-02-09 09:59:49 +08:00
|
|
|
|
};
|
2024-02-09 19:38:12 +08:00
|
|
|
|
g_codepage->setminmax(0,CP_UTF8);
|
2024-03-28 11:01:44 +08:00
|
|
|
|
|
|
|
|
|
mainlayout=new gridlayout();
|
|
|
|
|
mainlayout->addcontrol(new label(this,LblFlushDelay),0,0);
|
|
|
|
|
mainlayout->addcontrol(g_timeout,0,1);
|
|
|
|
|
|
|
|
|
|
mainlayout->addcontrol(new label(this,LblCodePage),1,0);
|
|
|
|
|
mainlayout->addcontrol(g_codepage,1,1);
|
|
|
|
|
|
|
|
|
|
mainlayout->addcontrol(new label(this,LblMaxBuff),2,0);
|
|
|
|
|
mainlayout->addcontrol(spinmaxbuffsize,2,1);
|
|
|
|
|
|
|
|
|
|
mainlayout->addcontrol(new label(this,LblMaxHist),3,0);
|
|
|
|
|
mainlayout->addcontrol(spinmaxhistsize,3,1);
|
|
|
|
|
|
|
|
|
|
mainlayout->addcontrol(ckbfilterrepeat,4,0,1,2);
|
|
|
|
|
mainlayout->addcontrol(g_check_clipboard,5,0,1,2);
|
|
|
|
|
mainlayout->addcontrol(autoattach,6,0,1,2);
|
|
|
|
|
mainlayout->addcontrol(autoattach_so,7,0,1,2);
|
|
|
|
|
mainlayout->addcontrol(readonlycheck,8,0,1,2);
|
|
|
|
|
|
|
|
|
|
setlayout(mainlayout);
|
2024-03-28 00:31:53 +08:00
|
|
|
|
setcentral(600,500);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
settext(WndSetting);
|
|
|
|
|
}
|
|
|
|
|
void Pluginwindow::on_size(int w,int h){
|
2024-03-30 00:40:49 +08:00
|
|
|
|
listplugins->setgeo(10,10,w-20,h-20);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
}
|
2024-03-29 15:07:43 +08:00
|
|
|
|
void Pluginwindow::pluginrankmove(int moveoffset){
|
|
|
|
|
auto idx=listplugins->currentidx();
|
|
|
|
|
if(idx==-1)return;
|
|
|
|
|
auto idx2=idx+moveoffset;
|
|
|
|
|
auto a=min(idx,idx2),b=max(idx,idx2);
|
|
|
|
|
if(a<0||b>=listplugins->count())return;
|
|
|
|
|
pluginmanager->swaprank(a,b);
|
|
|
|
|
|
|
|
|
|
auto pa=((LPCWSTR)listplugins->getdata(a));
|
|
|
|
|
auto pb=((LPCWSTR)listplugins->getdata(b));
|
|
|
|
|
|
|
|
|
|
listplugins->deleteitem(a);
|
|
|
|
|
listplugins->insertitem(b,std::filesystem::path(pa).stem());
|
|
|
|
|
listplugins->setdata(b,(LONG_PTR)pa);
|
|
|
|
|
}
|
2024-03-29 18:07:15 +08:00
|
|
|
|
Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginmanager(pl){
|
2024-03-30 00:40:49 +08:00
|
|
|
|
|
2024-02-09 09:25:26 +08:00
|
|
|
|
static auto listadd=[&](const std::wstring& s){
|
2024-02-12 00:17:58 +08:00
|
|
|
|
auto idx=listplugins->additem(std::filesystem::path(s).stem());
|
2024-02-09 19:38:12 +08:00
|
|
|
|
auto _s=new wchar_t[s.size()+1];wcscpy(_s,s.c_str());
|
|
|
|
|
listplugins->setdata(idx,(LONG_PTR)_s);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
};
|
2024-03-28 11:01:44 +08:00
|
|
|
|
listplugins = new listbox(this);
|
2024-02-09 09:25:26 +08:00
|
|
|
|
|
2024-03-29 18:07:15 +08:00
|
|
|
|
listplugins->on_menu=[&](){
|
|
|
|
|
Menu menu;
|
|
|
|
|
menu.add(MenuAddPlugin,[&](){
|
2024-03-29 15:07:43 +08:00
|
|
|
|
if(auto f=pluginmanager->selectpluginfile())
|
2024-03-29 15:57:38 +08:00
|
|
|
|
switch (auto res=pluginmanager->addplugin(f.value()))
|
|
|
|
|
{
|
|
|
|
|
case addpluginresult::success:
|
2024-03-29 15:07:43 +08:00
|
|
|
|
listadd(f.value());
|
2024-03-29 15:57:38 +08:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
std::map<addpluginresult,LPCWSTR> errorlog={
|
|
|
|
|
{addpluginresult::isnotaplugins,InvalidPlugin},
|
|
|
|
|
{addpluginresult::invaliddll,InvalidDll},
|
|
|
|
|
{addpluginresult::dumplicate,InvalidDump},
|
|
|
|
|
};
|
|
|
|
|
MessageBoxW(winId,errorlog[res],MsgError,0);
|
2024-02-09 19:38:12 +08:00
|
|
|
|
}
|
2024-03-29 18:07:15 +08:00
|
|
|
|
});
|
2024-03-29 15:07:43 +08:00
|
|
|
|
auto idx=listplugins->currentidx();
|
2024-03-29 18:07:15 +08:00
|
|
|
|
if(idx!=-1)
|
|
|
|
|
{
|
2024-03-29 21:46:24 +08:00
|
|
|
|
menu.add(MenuRemovePlugin,[&,idx](){
|
2024-03-30 00:40:49 +08:00
|
|
|
|
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx),false);
|
2024-03-29 18:07:15 +08:00
|
|
|
|
listplugins->deleteitem(idx);
|
|
|
|
|
});
|
|
|
|
|
menu.add_sep();
|
|
|
|
|
menu.add(MenuPluginRankUp,std::bind(&Pluginwindow::pluginrankmove,this,-1));
|
|
|
|
|
menu.add(MenuPluginRankDown,std::bind(&Pluginwindow::pluginrankmove,this,1));
|
|
|
|
|
menu.add_sep();
|
|
|
|
|
menu.add_checkable(MenuPluginEnable,pluginmanager->getenable(idx),[&,idx](bool check){
|
|
|
|
|
pluginmanager->setenable(idx,check);
|
2024-03-30 00:40:49 +08:00
|
|
|
|
if(check)
|
|
|
|
|
pluginmanager->addplugin((LPCWSTR)listplugins->getdata(idx),true);
|
|
|
|
|
else
|
|
|
|
|
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx),true);
|
2024-03-29 18:07:15 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return menu;
|
|
|
|
|
};
|
2024-03-29 15:07:43 +08:00
|
|
|
|
|
|
|
|
|
|
2024-03-29 18:07:15 +08:00
|
|
|
|
for(int i=0;i<pluginmanager->count();i++){
|
|
|
|
|
listadd(pluginmanager->getname(i));
|
2024-02-09 09:25:26 +08:00
|
|
|
|
}
|
|
|
|
|
settext(WndPlugins);
|
|
|
|
|
setcentral(500,400);
|
2024-03-28 19:24:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HooksearchText::call(std::set<DWORD>pids){
|
|
|
|
|
edittext->settext(L"");
|
|
|
|
|
checkok->onclick=[&,pids](){
|
|
|
|
|
close();
|
|
|
|
|
auto cp=codepage->getcurr();
|
|
|
|
|
if(!IsValidCodePage(cp)) return;
|
|
|
|
|
SearchParam sp = {};
|
|
|
|
|
sp.codepage=cp;
|
|
|
|
|
wcsncpy_s(sp.text, edittext->text().c_str(), PATTERN_SIZE - 1);
|
|
|
|
|
for(auto pid:pids)
|
|
|
|
|
Host::FindHooks(pid, sp);
|
|
|
|
|
};
|
|
|
|
|
show();
|
|
|
|
|
}
|
|
|
|
|
HooksearchText::HooksearchText(mainwindow* p):mainwindow(p){
|
|
|
|
|
codepage=new spinbox(this,Host::defaultCodepage);
|
|
|
|
|
codepage->setminmax(0,CP_UTF8);
|
|
|
|
|
|
|
|
|
|
edittext=new lineedit(this);
|
|
|
|
|
checkok=new button(this,BtnOk);
|
|
|
|
|
layout=new gridlayout();
|
|
|
|
|
layout->addcontrol(new label(this,HS_TEXT),0,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_CODEPAGE),1,0);
|
|
|
|
|
layout->addcontrol(edittext,0,1);
|
|
|
|
|
layout->addcontrol(codepage,1,1);
|
|
|
|
|
layout->addcontrol(checkok,2,1);
|
|
|
|
|
|
|
|
|
|
setlayout(layout);
|
|
|
|
|
setcentral(500,200);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
std::wstring tohex(BYTE* bs,int len){
|
|
|
|
|
std::wstring buffer;
|
|
|
|
|
for (int i = 0; i < len; i += 1){
|
|
|
|
|
buffer.append(FormatString(L"%02hX ", bs[i]));
|
|
|
|
|
}
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
std::wstring addr2hex(uintptr_t addr){
|
|
|
|
|
return FormatString(L"%p",addr);
|
|
|
|
|
}
|
|
|
|
|
void realcallsearchhooks(std::set<DWORD>pids,std::wstring filter,SearchParam sp){
|
|
|
|
|
|
|
|
|
|
auto hooks = std::make_shared<std::vector<std::wstring>>();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
for(auto processId:pids)
|
|
|
|
|
Host::FindHooks(processId, sp,
|
|
|
|
|
[hooks, filter](HookParam hp, std::wstring text)
|
|
|
|
|
{
|
|
|
|
|
std::wsmatch matches;
|
|
|
|
|
if (std::regex_search(text, matches, std::wregex(filter))) {
|
|
|
|
|
hooks->emplace_back(std::wstring(hp.hookcode)+L"=>"+text);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
catch (std::exception &e) {
|
|
|
|
|
//std::wcout<<e.what();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::thread([hooks]
|
|
|
|
|
{
|
|
|
|
|
for (int lastSize = 0; hooks->size() == 0 || hooks->size() != lastSize; Sleep(2000)) lastSize = hooks->size();
|
|
|
|
|
|
|
|
|
|
std::ofstream of;
|
|
|
|
|
of.open("savehooks.txt");
|
|
|
|
|
for (auto line:*hooks) of<<WideStringToString(line)<<"\n";
|
|
|
|
|
of.close();
|
|
|
|
|
hooks->clear();
|
|
|
|
|
}).detach();
|
|
|
|
|
}
|
|
|
|
|
Hooksearchsetting::Hooksearchsetting(mainwindow* p):mainwindow(p){
|
|
|
|
|
layout=new gridlayout();
|
|
|
|
|
SearchParam sp{};
|
|
|
|
|
spinduration=new spinbox(this,sp.searchTime);
|
|
|
|
|
spinoffset=new spinbox(this,sp.offset);
|
|
|
|
|
spincap=new spinbox(this,sp.maxRecords);
|
|
|
|
|
spincodepage=new spinbox(this,Host::defaultCodepage);
|
|
|
|
|
editpattern=new lineedit(this);
|
|
|
|
|
editpattern->settext(tohex(sp.pattern,sp.length));
|
|
|
|
|
editmodule=new lineedit(this);
|
|
|
|
|
editmaxaddr=new lineedit(this);
|
|
|
|
|
editmaxaddr->settext(addr2hex(sp.maxAddress));
|
|
|
|
|
editminaddr=new lineedit(this);
|
|
|
|
|
editminaddr->settext(addr2hex(sp.minAddress));
|
|
|
|
|
spinpadding=new spinbox(this,0);
|
|
|
|
|
editregex=new lineedit(this);
|
|
|
|
|
start=new button(this,HS_START_HOOK_SEARCH);
|
|
|
|
|
layout->addcontrol(new label(this,HS_SEARCH_PATTERN),0,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_SEARCH_DURATION),1,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_PATTERN_OFFSET),2,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_MAX_HOOK_SEARCH_RECORDS),3,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_CODEPAGE),4,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_SEARCH_MODULE),5,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_MIN_ADDRESS),6,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_MAX_ADDRESS),7,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_STRING_OFFSET),8,0);
|
|
|
|
|
layout->addcontrol(new label(this,HS_HOOK_SEARCH_FILTER),9,0);
|
|
|
|
|
layout->addcontrol(start,10,1);
|
|
|
|
|
|
|
|
|
|
layout->addcontrol(editpattern,0,1);
|
|
|
|
|
layout->addcontrol(spinduration,1,1);
|
|
|
|
|
layout->addcontrol(spinoffset,2,1);
|
|
|
|
|
layout->addcontrol(spincap,3,1);
|
|
|
|
|
layout->addcontrol(spincodepage,4,1);
|
|
|
|
|
layout->addcontrol(editmodule,5,1);
|
|
|
|
|
layout->addcontrol(editminaddr,6,1);
|
|
|
|
|
layout->addcontrol(editmaxaddr,7,1);
|
|
|
|
|
layout->addcontrol(spinpadding,8,1);
|
|
|
|
|
layout->addcontrol(editregex,9,1);
|
|
|
|
|
|
|
|
|
|
setlayout(layout);
|
|
|
|
|
setcentral(1000,600);
|
|
|
|
|
}
|
|
|
|
|
std::vector<BYTE> hexStringToBytes(const std::wstring& hexString_) {
|
|
|
|
|
auto hexString=hexString_;
|
|
|
|
|
strReplace(hexString,L" ",L"");
|
|
|
|
|
strReplace(hexString,L"??",FormatString(L"%02hX",XX));
|
|
|
|
|
std::vector<BYTE> bytes;
|
|
|
|
|
if (hexString.length() % 2 != 0) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < hexString.size() / 2; i++) {
|
|
|
|
|
auto byteValue = std::stoi(hexString.substr(i*2,2), nullptr, 16);
|
|
|
|
|
bytes.push_back(byteValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
|
}
|
|
|
|
|
void Hooksearchsetting::call(std::set<DWORD>pids,std::wstring reg){
|
|
|
|
|
if(pids.empty())return;
|
|
|
|
|
|
|
|
|
|
if(auto filename=gmf(*pids.begin()))
|
|
|
|
|
editmodule->settext(std::filesystem::path(filename.value()).filename().wstring());
|
|
|
|
|
editregex->settext(reg);
|
|
|
|
|
spincodepage->setcurr(Host::defaultCodepage);
|
|
|
|
|
|
|
|
|
|
start->onclick=[&,pids](){
|
|
|
|
|
close();
|
|
|
|
|
SearchParam sp{};
|
|
|
|
|
sp.searchTime=spinduration->getcurr();
|
|
|
|
|
sp.offset=spinoffset->getcurr();
|
|
|
|
|
sp.maxRecords=spincap->getcurr();
|
|
|
|
|
sp.codepage=spincodepage->getcurr();
|
|
|
|
|
|
|
|
|
|
if(editpattern->text().find(L".")==std::wstring::npos){
|
|
|
|
|
auto hex=hexStringToBytes(editpattern->text());
|
|
|
|
|
memcpy(sp.pattern,hex.data(),hex.size());
|
|
|
|
|
sp.length=hex.size();
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
wcsncpy_s(sp.exportModule, editpattern->text().c_str(), MAX_MODULE_SIZE - 1);
|
|
|
|
|
sp.length = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wcscpy(sp.boundaryModule,editmodule->text().c_str());
|
|
|
|
|
sp.minAddress=std::stoll(editminaddr->text(), nullptr, 16);
|
|
|
|
|
sp.maxAddress=std::stoll(editmaxaddr->text(), nullptr, 16);
|
|
|
|
|
sp.padding=spinpadding->getcurr();
|
|
|
|
|
realcallsearchhooks(pids,editregex->text(),sp);
|
|
|
|
|
};
|
|
|
|
|
show();
|
|
|
|
|
}
|
|
|
|
|
Hooksearchwindow::Hooksearchwindow(LunaHost* host):mainwindow(host){
|
|
|
|
|
|
|
|
|
|
cjkcheck=new checkbox(this,SEARCH_CJK);
|
2024-03-29 22:18:52 +08:00
|
|
|
|
hs_default=new button(this,HS_START_HOOK_SEARCH);
|
2024-03-28 19:24:07 +08:00
|
|
|
|
hs_text=new button(this,HS_SEARCH_FOR_TEXT);
|
|
|
|
|
hs_user=new button(this,HS_SETTINGS);
|
|
|
|
|
|
|
|
|
|
layout=new gridlayout();
|
|
|
|
|
layout->addcontrol(cjkcheck,0,0,1,3);
|
|
|
|
|
layout->addcontrol(hs_default,1,0);
|
|
|
|
|
layout->addcontrol(hs_text,1,1);
|
|
|
|
|
layout->addcontrol(hs_user,1,2);
|
|
|
|
|
|
|
|
|
|
setlayout(layout);
|
|
|
|
|
|
|
|
|
|
settext(BtnSearchHook);
|
|
|
|
|
setcentral(800,200);
|
|
|
|
|
|
|
|
|
|
auto dohooksearchdispatch=[&,host](int type)
|
|
|
|
|
{
|
|
|
|
|
close();
|
|
|
|
|
if(type==1)
|
|
|
|
|
{
|
|
|
|
|
if(hooksearchText==0) hooksearchText=new HooksearchText(this);
|
|
|
|
|
hooksearchText->call(host->attachedprocess);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto filter=(cjkcheck->ischecked()?L"[\\u3000-\\ua000]{4,}" : L"[\\u0020-\\u1000]{4,}");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(type==0)
|
|
|
|
|
{
|
|
|
|
|
SearchParam sp = {};
|
|
|
|
|
sp.codepage = Host::defaultCodepage;
|
|
|
|
|
sp.length = 0;
|
|
|
|
|
realcallsearchhooks(host->attachedprocess,filter,sp);
|
|
|
|
|
}
|
|
|
|
|
else if(type==2)
|
|
|
|
|
{
|
|
|
|
|
if(hooksearchsetting==0) hooksearchsetting=new Hooksearchsetting(this);
|
|
|
|
|
hooksearchsetting->call(host->attachedprocess,filter);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
hs_default->onclick=std::bind(dohooksearchdispatch,0);
|
|
|
|
|
hs_text->onclick=std::bind(dohooksearchdispatch,1);
|
|
|
|
|
hs_user->onclick=std::bind(dohooksearchdispatch,2);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
}
|