diff --git a/.gitignore b/.gitignore index 01a744d..8e86036 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ .idea/ out/ G-Earth2.iml +/G-WinMem/.vs +/G-WinMem/x64 +/G-WinMem/G-WinMem/x64 /Extensions/ G-Earth.iml +/G-EarthWindows.iml \ No newline at end of file diff --git a/G-WinMem/G-WinMem.sln b/G-WinMem/G-WinMem.sln new file mode 100644 index 0000000..65152d4 --- /dev/null +++ b/G-WinMem/G-WinMem.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2018 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "G-WinMem", "G-WinMem\G-WinMem.vcxproj", "{D445BBD6-23E4-40AD-BB05-39E0401D7421}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Debug|x64.ActiveCfg = Debug|x64 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Debug|x64.Build.0 = Debug|x64 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Debug|x86.ActiveCfg = Debug|Win32 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Debug|x86.Build.0 = Debug|Win32 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Release|x64.ActiveCfg = Release|x64 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Release|x64.Build.0 = Release|x64 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Release|x86.ActiveCfg = Release|Win32 + {D445BBD6-23E4-40AD-BB05-39E0401D7421}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CDDBAEFF-CFB7-4167-88D9-015827207E0C} + EndGlobalSection +EndGlobal diff --git a/G-WinMem/G-WinMem/G-WinMem.cpp b/G-WinMem/G-WinMem/G-WinMem.cpp new file mode 100644 index 0000000..dfc79e5 Binary files /dev/null and b/G-WinMem/G-WinMem/G-WinMem.cpp differ diff --git a/G-WinMem/G-WinMem/G-WinMem.vcxproj b/G-WinMem/G-WinMem/G-WinMem.vcxproj new file mode 100644 index 0000000..58e6a36 --- /dev/null +++ b/G-WinMem/G-WinMem/G-WinMem.vcxproj @@ -0,0 +1,169 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {D445BBD6-23E4-40AD-BB05-39E0401D7421} + Win32Proj + GWinMem + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + \ No newline at end of file diff --git a/G-WinMem/G-WinMem/G-WinMem.vcxproj.filters b/G-WinMem/G-WinMem/G-WinMem.vcxproj.filters new file mode 100644 index 0000000..ebe7bb6 --- /dev/null +++ b/G-WinMem/G-WinMem/G-WinMem.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/G-WinMem/G-WinMem/G-WinMem.vcxproj.user b/G-WinMem/G-WinMem/G-WinMem.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/G-WinMem/G-WinMem/G-WinMem.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/G-WinMem/G-WinMem/Process.cpp b/G-WinMem/G-WinMem/Process.cpp new file mode 100644 index 0000000..5de022a --- /dev/null +++ b/G-WinMem/G-WinMem/Process.cpp @@ -0,0 +1,263 @@ + +#include "ctpl_stl.h" +#include "Process.h" + +#include +#include + +Process::Process() : Process(0) +{} + +Process::Process(int pid) + : mPid(pid), + mHandle(nullptr) +{} + +bool Process::Open() +{ + mHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_OPERATION, false, mPid); + + return true; +} + +std::vector Process::GetChunks() +{ + return mChunks; +} + +void Process::Close() +{ + CloseHandle(mHandle); +} + +void Process::PrintCachedResults(std::vector cache) +{ + const auto offset = 4; + static std::mutex m; + Open(); + + for (auto addr : cache) { + u_char rawMem[1024] = { 0 }; + + if (!ReadProcessMemory(mHandle, addr, rawMem, 1024, nullptr)) + { + std::cerr << "Failed to read memory at " << addr << std::endl; + return; + } + + for (auto i = 0; i < (1024 - ((256 - 1) * offset)); i += offset) + { + unsigned char wannabeRC4data[1024] = { 0 }; + unsigned char data[256] = { 0 }; + memcpy(wannabeRC4data, rawMem + i, 1024); + + auto isvalid = true; + + for (auto j = 0; j < 1024; j++) + { + if (j % 4 != 0 && wannabeRC4data[j] != 0) + { + isvalid = false; + break; + } + if (j % 4 == 0) + { + data[j / 4] = wannabeRC4data[j]; + } + } + if (isvalid) + { + m.lock(); + for (auto idx : data) + printf("%02X", static_cast(idx) & 0xFF); + + std::cout << std::endl; + m.unlock(); + } + } + } + Close(); +} + +void Process::PrintRC4Possibilities() +{ + SYSTEM_INFO sys_info; + + static std::mutex m; + + GetSystemInfo(&sys_info); + + Open(); + + FindMaps(sys_info); + + const auto offset = 4; + + CreateMapsForRC4(); + + for (auto k = 0; k < mRC4Maps.size(); k++) + { + auto mem = mRC4Maps[k]; + + if (mem->mSize >= 1024 && mem->mSize <= 1024 + 2 * offset) + { + for (auto i = 0; i < (mem->mSize - ((256 - 1) * offset)); i += offset) + { + unsigned char wannabeRC4data[1024] = { 0 }; + unsigned char data[256] = { 0 }; + memcpy(wannabeRC4data, static_cast(mem->mStart) + i, 1024); + + auto isvalid = true; + + for (auto j = 0; j < 1024; j++) + { + if (j % 4 != 0 && wannabeRC4data[j] != 0) + { + isvalid = false; + break; + } + if (j % 4 == 0) + { + data[j / 4] = wannabeRC4data[j]; + } + } + if (isvalid) + { + m.lock(); + printf("%llx\n",reinterpret_cast(mOutCache[k])); + for (auto idx : data) + printf("%02X", static_cast(idx) & 0xFF); + + std::cout << std::endl; + m.unlock(); + } + } + } + delete mem; + } + Close(); +} + +void Process::CreateMapFromChunk(MemoryChunk *chunk) +{ + const auto offset = 4; + const auto dump = new unsigned char[chunk->mSize + 1]; + + memset(dump, 0, chunk->mSize + 1); + + if (!ReadProcessMemory(mHandle, chunk->mStart, dump, chunk->mSize, nullptr)) + { + std::cerr << "Failed to read memory at: " << chunk->mStart << std::endl; + return; + } + + auto maskCount = 0; + int nToMap[256] = { 0 }; + int removeMap[256] = { 0 }; + + for (auto i = 0; i < 256; i++) { + nToMap[i] = -1; + removeMap[i] = -1; + } + + auto matchStart = -1; + auto matchEnd = -1; + + for (auto i = 0; i < chunk->mSize; i += offset) + { + const auto b = (static_cast(dump[i]) + 128) % 256; + const auto indInMap = (i / 4) % 256; + + const auto deletedNumber = removeMap[indInMap]; + + if (deletedNumber != -1) + { + nToMap[deletedNumber] = -1; + maskCount--; + removeMap[indInMap] = -1; + } + + if (nToMap[b] == -1) + { + maskCount++; + removeMap[indInMap] = b; + nToMap[b] = indInMap; + } + else + { + removeMap[nToMap[b]] = -1; + removeMap[indInMap] = b; + nToMap[b] = indInMap; + } + + if (maskCount == 256) + { + if (matchStart == -1) + { + matchStart = i - ((256 - 1) * offset); + matchEnd = i; + } + + if (matchEnd < i - ((256 - 1) * offset)) + { + //printf("maybeValid -> %p\n", static_cast(chunk->mStart) + matchStart); + mOutCache.push_back(static_cast(chunk->mStart) + matchStart); + mRC4Maps.push_back(new MemoryChunk(dump + matchStart, matchEnd - matchStart + 4)); + + matchStart = i - ((256 - 1) * offset); + } + matchEnd = i; + } + } + if (matchStart != -1) + { + mOutCache.push_back(static_cast(chunk->mStart) + matchStart); + mRC4Maps.push_back(new MemoryChunk(dump + matchStart, matchEnd - matchStart + 4)); + } + delete chunk; +} + +void Process::CreateMapsForRC4() +{ + ctpl::thread_pool p(5); + + for (auto chunk : mChunks) { + p.push(std::bind(&Process::CreateMapFromChunk, this, chunk)); + } + + p.stop(true); +} + + + +void Process::FindMaps(SYSTEM_INFO sys_info) +{ + + auto addr = reinterpret_cast(sys_info.lpMinimumApplicationAddress); + const auto end = reinterpret_cast(sys_info.lpMaximumApplicationAddress); + + MEMORY_BASIC_INFORMATION mbi; + + while (addr < end) { + if (!VirtualQueryEx(mHandle, reinterpret_cast(addr), &mbi, sizeof(mbi))) { + std::cerr << "Failed to get memory maps\n"; + return; + } + + if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_GUARD) == 0) && ((mbi.Protect & PAGE_NOACCESS) == 0)) { + mChunks.push_back(new MemoryChunk(reinterpret_cast(addr), mbi.RegionSize)); + } + addr += mbi.RegionSize; + } +} + + + +Process::~Process() +{ + for (auto m : mChunks) + delete m; + + for (auto m : mRC4Maps) + delete m; +} diff --git a/G-WinMem/G-WinMem/Process.h b/G-WinMem/G-WinMem/Process.h new file mode 100644 index 0000000..a12ff06 --- /dev/null +++ b/G-WinMem/G-WinMem/Process.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include + +class MemoryChunk +{ +public: + MemoryChunk(LPVOID start, SIZE_T size); + LPVOID mStart; + SIZE_T mSize; +}; + +inline MemoryChunk::MemoryChunk(LPVOID start, SIZE_T size) : + mStart(start), + mSize(size) +{} + + +class Process +{ +public: + Process(); + Process(int pid); + bool Open(); + void Close(); + void FindMaps(SYSTEM_INFO sys_info); + void CreateMapsForRC4(); + void CreateMapFromChunk(MemoryChunk *chunk); + void PrintRC4Possibilities(); + void PrintCachedResults(std::vector cache); + ~Process(); + std::vector GetChunks(); +private: + int mPid; + HANDLE mHandle; + std::vector mChunks; + std::vector mRC4Maps; + std::vector mOutCache; +}; + diff --git a/G-WinMem/G-WinMem/ctpl_stl.h b/G-WinMem/G-WinMem/ctpl_stl.h new file mode 100644 index 0000000..9b59bcd --- /dev/null +++ b/G-WinMem/G-WinMem/ctpl_stl.h @@ -0,0 +1,256 @@ +/********************************************************* +* +* Copyright (C) 2014 by Vitaliy Vitsentiy +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*********************************************************/ + + +#ifndef __ctpl_stl_thread_pool_H__ +#define __ctpl_stl_thread_pool_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +// thread pool to run user's functors with signature +// ret func(int id, other_params) +// where id is the index of the thread that runs the functor +// ret is some return type + + +namespace ctpl { + + namespace detail { + template + class Queue { + public: + bool push(T const & value) { + std::unique_lock lock(this->mutex); + this->q.push(value); + return true; + } + // deletes the retrieved element, do not use for non integral types + bool pop(T & v) { + std::unique_lock lock(this->mutex); + if (this->q.empty()) + return false; + v = this->q.front(); + this->q.pop(); + return true; + } + bool empty() { + std::unique_lock lock(this->mutex); + return this->q.empty(); + } + private: + std::queue q; + std::mutex mutex; + }; + } + + class thread_pool { + + public: + + thread_pool() { this->init(); } + thread_pool(int nThreads) { this->init(); this->resize(nThreads); } + + // the destructor waits for all the functions in the queue to be finished + ~thread_pool() { + this->stop(true); + } + + // get the number of running threads in the pool + int size() { return static_cast(this->threads.size()); } + + // number of idle threads + int n_idle() { return this->nWaiting; } + int n_pending() { return this->nPending; } + std::thread & get_thread(int i) { return *this->threads[i]; } + + // change the number of threads in the pool + // should be called from one thread, otherwise be careful to not interleave, also with this->stop() + // nThreads must be >= 0 + void resize(int nThreads) { + if (!this->isStop && !this->isDone) { + int oldNThreads = static_cast(this->threads.size()); + if (oldNThreads <= nThreads) { // if the number of threads is increased + this->threads.resize(nThreads); + this->flags.resize(nThreads); + + for (int i = oldNThreads; i < nThreads; ++i) { + this->flags[i] = std::make_shared>(false); + this->set_thread(i); + } + } + else { // the number of threads is decreased + for (int i = oldNThreads - 1; i >= nThreads; --i) { + *this->flags[i] = true; // this thread will finish + this->threads[i]->detach(); + } + { + // stop the detached threads that were waiting + std::unique_lock lock(this->mutex); + this->cv.notify_all(); + } + this->threads.resize(nThreads); // safe to delete because the threads are detached + this->flags.resize(nThreads); // safe to delete because the threads have copies of shared_ptr of the flags, not originals + } + } + } + + // empty the queue + void clear_queue() { + std::function * _f; + while (this->q.pop(_f)) + delete _f; // empty the queue + } + + // pops a functional wrapper to the original function + std::function pop() { + std::function * _f = nullptr; + this->q.pop(_f); + std::unique_ptr> func(_f); // at return, delete the function even if an exception occurred + std::function f; + if (_f) + f = *_f; + return f; + } + + // wait for all computing threads to finish and stop all threads + // may be called asynchronously to not pause the calling thread while waiting + // if isWait == true, all the functions in the queue are run, otherwise the queue is cleared without running the functions + void stop(bool isWait = false) { + if (!isWait) { + if (this->isStop) + return; + this->isStop = true; + for (int i = 0, n = this->size(); i < n; ++i) { + *this->flags[i] = true; // command the threads to stop + } + this->clear_queue(); // empty the queue + } + else { + if (this->isDone || this->isStop) + return; + this->isDone = true; // give the waiting threads a command to finish + } + { + std::unique_lock lock(this->mutex); + this->cv.notify_all(); // stop all waiting threads + } + for (int i = 0; i < static_cast(this->threads.size()); ++i) { // wait for the computing threads to finish + if (this->threads[i]->joinable()) + this->threads[i]->join(); + } + // if there were no threads in the pool but some functors in the queue, the functors are not deleted by the threads + // therefore delete them here + this->clear_queue(); + this->threads.clear(); + this->flags.clear(); + } + + template + auto push(F && f, Rest&&... rest) ->std::future { + auto pck = std::make_shared>( + std::bind(std::forward(f), std::placeholders::_1, std::forward(rest)...) + ); + auto _f = new std::function([pck](int id) { + (*pck)(id); + }); + ++this->nPending; + this->q.push(_f); + std::unique_lock lock(this->mutex); + this->cv.notify_one(); + return pck->get_future(); + } + + // run the user's function that excepts argument int - id of the running thread. returned value is templatized + // operator returns std::future, where the user can get the result and rethrow the catched exceptins + template + auto push(F && f) ->std::future { + auto pck = std::make_shared>(std::forward(f)); + auto _f = new std::function([pck](int id) { + (*pck)(id); + }); + ++this->nPending; + this->q.push(_f); + std::unique_lock lock(this->mutex); + this->cv.notify_one(); + return pck->get_future(); + } + + + private: + + // deleted + thread_pool(const thread_pool &);// = delete; + thread_pool(thread_pool &&);// = delete; + thread_pool & operator=(const thread_pool &);// = delete; + thread_pool & operator=(thread_pool &&);// = delete; + + void set_thread(int i) { + std::shared_ptr> flag(this->flags[i]); // a copy of the shared ptr to the flag + auto f = [this, i, flag/* a copy of the shared ptr to the flag */]() { + std::atomic & _flag = *flag; + std::function * _f; + bool isPop = this->q.pop(_f); + while (true) { + while (isPop) { // if there is anything in the queue + --this->nPending; + std::unique_ptr> func(_f); // at return, delete the function even if an exception occurred + (*_f)(i); + if (_flag) + return; // the thread is wanted to stop, return even if the queue is not empty yet + else + isPop = this->q.pop(_f); + } + // the queue is empty here, wait for the next command + std::unique_lock lock(this->mutex); + ++this->nWaiting; + this->cv.wait(lock, [this, &_f, &isPop, &_flag]() { isPop = this->q.pop(_f); return isPop || this->isDone || _flag; }); + --this->nWaiting; + if (!isPop) + return; // if the queue is empty and this->isDone == true or *flag then return + } + }; + this->threads[i].reset(new std::thread(f)); // compiler may not support std::make_unique() + } + + void init() { this->nWaiting = 0; this->nPending = 0; this->isStop = false; this->isDone = false; } + + std::vector> threads; + std::vector>> flags; + detail::Queue *> q; + std::atomic isDone; + std::atomic isStop; + std::atomic nWaiting; // how many threads are waiting + std::atomic nPending; // how many tasks are waiting + + std::mutex mutex; + std::condition_variable cv; + }; + +} + +#endif // __ctpl_stl_thread_pool_H__ \ No newline at end of file diff --git a/G-WinMem/G-WinMem/stdafx.cpp b/G-WinMem/G-WinMem/stdafx.cpp new file mode 100644 index 0000000..56288a9 Binary files /dev/null and b/G-WinMem/G-WinMem/stdafx.cpp differ diff --git a/G-WinMem/G-WinMem/stdafx.h b/G-WinMem/G-WinMem/stdafx.h new file mode 100644 index 0000000..94d4ed8 Binary files /dev/null and b/G-WinMem/G-WinMem/stdafx.h differ diff --git a/G-WinMem/G-WinMem/targetver.h b/G-WinMem/G-WinMem/targetver.h new file mode 100644 index 0000000..567cd34 Binary files /dev/null and b/G-WinMem/G-WinMem/targetver.h differ diff --git a/src/g_earth/protocol/memory/habboclient/windows/WindowsHabboClient.java b/src/g_earth/protocol/memory/habboclient/windows/WindowsHabboClient.java index 6bc9148..3410787 100644 --- a/src/g_earth/protocol/memory/habboclient/windows/WindowsHabboClient.java +++ b/src/g_earth/protocol/memory/habboclient/windows/WindowsHabboClient.java @@ -1,312 +1,142 @@ package g_earth.protocol.memory.habboclient.windows; -//import com.sun.jna.Memory; -//import com.sun.jna.Native; -//import com.sun.jna.Pointer; -//import com.sun.jna.platform.win32.Kernel32; -//import com.sun.jna.platform.win32.User32; -//import com.sun.jna.platform.win32.WinBase; -//import com.sun.jna.platform.win32.WinNT; -//import com.sun.jna.ptr.IntByReference; -import g_earth.protocol.HConnection; -import g_earth.protocol.memory.habboclient.HabboClient; +import g_earth.misc.Cacher; +import g_earth.protocol.HConnection; +import g_earth.protocol.HMessage; +import g_earth.protocol.TrafficListener; +import g_earth.protocol.memory.habboclient.HabboClient; +import org.json.simple.JSONObject; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URISyntaxException; import java.util.*; /** * Created by Jeunez on 27/06/2018. */ - -/* - * not functional class - */ - public class WindowsHabboClient extends HabboClient { public WindowsHabboClient(HConnection connection) { super(connection); + + connection.addTrafficListener(0, message -> { + if (message.getDestination() == HMessage.Side.TOSERVER && message.getPacket().headerId() == PRODUCTIONID) { + production = message.getPacket().readString(); + } + }); + } + + private static final int PRODUCTIONID = 4000; + private String production = ""; + + private String getOffsetsCacheKey() { + return "RC4Offsets"; + } + + private String getOffsetsRevision() { + return production; } @Override public List getRC4cached() { - return new ArrayList<>(); + List result = new ArrayList<>(); + try { + List possibleResults = readPossibleBytes(true); + + if (possibleResults == null) + return new ArrayList<>(); + + for (String s : possibleResults) + result.add(hexStringToByteArray(s)); + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + return result; + } + + private ArrayList readPossibleBytes(boolean useCache) throws IOException, URISyntaxException { + ProcessBuilder pb = null; + JSONObject revisionList = (JSONObject) Cacher.get(getOffsetsCacheKey()); + + if (revisionList == null) { + Cacher.put(getOffsetsCacheKey(), new JSONObject()); + revisionList = (JSONObject) Cacher.get(getOffsetsCacheKey()); // refresh + } + + List cachedOffsets = (List) revisionList.get(getOffsetsRevision()); + StringJoiner joiner = new StringJoiner(" "); + + if (useCache) { + if (cachedOffsets == null) { + return null; + } + + for (String s : cachedOffsets) { + joiner.add(s); + } + } + + if (!useCache) + pb = new ProcessBuilder(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + "\\G-WinMem.exe", hConnection.getClientHostAndPort().substring(0, hConnection.getClientHostAndPort().indexOf(':')) , Integer.toString(hConnection.getPort())); + else + pb = new ProcessBuilder(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent() + "\\G-WinMem.exe", hConnection.getClientHostAndPort().substring(0, hConnection.getClientHostAndPort().indexOf(':')) , Integer.toString(hConnection.getPort()), "-c" + joiner.toString()); + + + Process p = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + + String line; + ArrayList possibleData = new ArrayList<>(); + + if (cachedOffsets == null) { + cachedOffsets = new ArrayList<>(); + } + + + int count = 0; + while((line = reader.readLine()) != null) { + if (line.length() > 1) { + if (!useCache && (count++ % 2 == 0)) { + if (!cachedOffsets.contains(line)) { + cachedOffsets.add(line); + } + } + else + possibleData.add(line); + } + } + revisionList.put(getOffsetsRevision(), cachedOffsets); + Cacher.put(getOffsetsCacheKey(), revisionList); + p.destroy(); + return possibleData; } @Override public List getRC4possibilities() { - return null; - } -// -// private static final boolean DEBUG = true; -// private List possibleFlashTasks; -// -// static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class); -// static User32 user32 = (User32) Native.loadLibrary("user32", User32.class); -// -// public static int PROCESS_VM_READ= 0x0010; -// public static int PROCESS_VM_WRITE = 0x0020; -// public static int PROCESS_VM_OPERATION = 0x0008; -// -// -// public WindowsHabboClient(HConnection connection) { -// super(connection); -// } -// -// static class WindowsTask { -// public String name; -// public int PID; -// public String session_name; -// public int sessionNumber; -// public int mem_usage; -// -// public WindowsTask(String name, int PID, String sessions_name, int sessionNumber, int mem_usage) { -// this.name = name; -// this.PID = PID; -// this.session_name = sessions_name; -// this.sessionNumber = sessionNumber; -// this.mem_usage = mem_usage; -// } -// -// @Override -// public String toString() { -// return "name: " + name + ", PID: " + PID + ", memory: " + mem_usage; -// } -// } -// -// private static List execute_command(String command) { -// List result = new ArrayList<>(); -// try { -// Process process = Runtime.getRuntime().exec(command); -// BufferedReader reader=new BufferedReader( new InputStreamReader(process.getInputStream())); -// String s; -// while ((s = reader.readLine()) != null){ -// result.add(s); -// } -// } catch (IOException e) { -// e.printStackTrace(); -// } -// return result; -// } -// private static List splitStringExtra(String s, String regex ) { -// String[] split = s.split(regex); -// -// List realSplit = new ArrayList<>(); -// for (String spli : split) { -// if (!spli.equals("") && !spli.equals(" ")) { -// realSplit.add(spli); -// } -// } -// -// return realSplit; -// } -// private static List parseTaskList(List lines) { -// List windowsTasks = new ArrayList<>(); -// -// final int ARG_COUNT = 5; -// boolean listHasStarted = false; -// int[] paramLengths = new int[ARG_COUNT]; -// for (String line : lines) { -// -// if (!listHasStarted && line.startsWith("=")) { -// List splitted = splitStringExtra(line, " "); -// if (splitted.size() == ARG_COUNT) { -// listHasStarted = true; -// for (int i = 0; i < ARG_COUNT; i++) { -// paramLengths[i] = splitted.get(i).length(); -// } -// } -// } -// else if (listHasStarted && splitStringExtra(line, " ").size() >= 5) { -// int v = 0; -// String[] args = new String[ARG_COUNT]; -// for (int i = 0; i < ARG_COUNT; i++) { -// int endindex = v + paramLengths[i]; -// args[i] = trim(line.substring(v, endindex)); -// v = endindex + 1; -// } -// -// WindowsTask task = new WindowsTask( -// args[0], -// Integer.parseInt(args[1]), -// args[2], -// Integer.parseInt(args[3]), -// obtainMemorySizeFromCMDString(args[4]) -// ); -// -// windowsTasks.add(task); -// } -// -// } -// -// return windowsTasks; -// } -// private static String trim(String s) { -// int start = 0; -// for (int i = 0; i < s.length(); i++) { -// if (s.charAt(i) == ' ') start++; -// else break; -// } -// -// int end = s.length(); -// for (int i = s.length() - 1; i >= 0; i--) { -// if (s.charAt(i) == ' ') end--; -// else break; -// } -// -// return s.substring(start, end); -// } -// private static int obtainMemorySizeFromCMDString(String s) { -// s = s.replaceAll("[^0-9A-Z]","") -// .replace("K","000") -// .replace("M", "000000") -// .replace("G", "000000000"); -// return Integer.parseInt(s); -// } -// -// private void obtain_PIDs() { -// int headPID = -1; -// -// -// String command1 = "cmd /C netstat -a -o -n | findstr "+hConnection.getClientHostAndPort()+" | findstr ESTABLISHED"; -// List connections = execute_command(command1); -// for (String s : connections) { -// List realSplit = splitStringExtra(s, " "); -// -// if (realSplit.size() > 1 && realSplit.get(1).equals(hConnection.getClientHostAndPort())) { -// headPID = Integer.parseInt(realSplit.get(4)); -// } -// } -// -// -// -// String command2 = "cmd /C tasklist"; -// List tasks = execute_command(command2); -// List taskList = parseTaskList(tasks); -// -// WindowsTask matchWithPID = null; -// int i = 0; -// while (matchWithPID == null && i < taskList.size()) { -// WindowsTask task = taskList.get(i); -// if (task.PID == headPID) { -// matchWithPID = task; -// } -// i++; -// } -// -// possibleFlashTasks = new ArrayList<>(); -// if (matchWithPID != null) { -// for (WindowsTask task : taskList) { -// if (task.name.equals(matchWithPID.name)) { -// possibleFlashTasks.add(task); -// } -// } -// } -// -// -// -// } -// -// @Override -// public List getRC4possibilities() { -// obtain_PIDs(); -// -// List possibilities = new ArrayList<>(); -// -// int[] count = {0}; -// for (int i = 0; i < possibleFlashTasks.size(); i++) { -// WindowsTask task = possibleFlashTasks.get(i); -// if (DEBUG) System.out.println("Potential task " + task); -// -// new Thread(() -> { -// List sublist = getRC4possibilities(task.PID, task.mem_usage); -// -// synchronized (count) { -// possibilities.addAll(sublist); -// count[0] ++; -// } -// -// }).start(); -// } -// -// while (count[0] != possibleFlashTasks.size() + 1) { // the +1 is temporary, to keep this function blocking untill it's functional -// try { -// Thread.sleep(1); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// } -// -// return possibilities; -// } -// -// public List getRC4possibilities(int processID, int processMemorySize) { -// List result = new ArrayList<>(); -// -//// user32.GetWindowThreadProcessId() -// WinNT.HANDLE process = kernel32.OpenProcess(PROCESS_VM_READ|PROCESS_VM_OPERATION, true, processID); -// -// IntByReference test = new IntByReference(0); -// Memory output = new Memory(100000); -// System.out.println(kernel32.ReadProcessMemory(process, new Pointer(0), output, 100000, test)); -// System.out.println(test.getValue()); -// -// int[] counter = new int[256]; -// int p = 0; -// while (p < output.size()) { -// counter[(output.getByte(p) + 256) % 256] ++; -// p += 4; -// } -// -//// for (int i = 0; i < counter.length; i++) { -//// System.out.println("counter " + i + " = " + counter[i]); -//// } -// -//// WinNT.HANDLE process = kernel32.OpenProcess(PROCESS_VM_READ|PROCESS_VM_OPERATION, true, processID); -//// Memory out = new Memory(processMemorySize); -//// kernel32.ReadProcessMemory(process, new Pointer(0), out, processMemorySize, new IntByReference()); -//// -//// int[] counter = new int[256]; -//// int p = 0; -//// while (p < out.size()) { -//// counter[((out.getByte(p)) + 256) % 256] ++; -//// p += 4; -//// } -//// -//// HashMap> mapper = new HashMap<>(); -//// HashSet allvalues = new HashSet<>(); -//// for (int i = 0; i < counter.length; i++) { -//// if (!mapper.containsKey(counter[i])) { -//// mapper.put(counter[i], new ArrayList<>()); -//// } -//// mapper.get(counter[i]).add(i); -//// allvalues.add(counter[i]); -//// } -////// System.out.println(allvalues.size()); -//// ArrayList allvalues2 = new ArrayList<>(allvalues); -//// allvalues2.sort(Integer::compareTo); -//// -//// StringBuilder sttt = new StringBuilder(); -//// sttt.append("process ").append(processID).append(", "); -//// for (int i = 1; i < Math.min(4, allvalues2.size()+1); i++) { -//// int occ = allvalues2.get(allvalues2.size() - i); -//// sttt .append(i) -//// .append(": ") -//// .append(mapper.get(occ).get(0)) -//// .append(" with ") -//// .append(occ) -//// .append(" occurences, "); -//// } -//// System.out.println(sttt); -// -// return result; -// } -// -// public static void main(String[] args) { -// String command2 = "cmd /C tasklist"; -// List tasks = execute_command(command2); -// List taskList = parseTaskList(tasks); -// -// System.out.println("t"); -// } + List result = new ArrayList<>(); + try { + ArrayList possibleData = readPossibleBytes(false); + for (String possibleHexStr : possibleData) { + result.add(hexStringToByteArray(possibleHexStr)); + } + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + return result; + } + + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i+1), 16)); + } + return data; + } }