-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5473458
Showing
14 changed files
with
842 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
build/ | ||
.vscode | ||
*.dll |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "pe-parse"] | ||
path = pe-parse | ||
url = https://github.com/trailofbits/pe-parse.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
cmake_minimum_required(VERSION 3.12) | ||
project(linoodle) | ||
enable_language(ASM) | ||
find_package(Threads REQUIRED) | ||
|
||
# Build PE parser library | ||
option(BUILD_SHARED_LIBS "" OFF) | ||
add_subdirectory(pe-parse) | ||
set(BUILD_SHARED_LIBS ON) | ||
|
||
# Build linoodle | ||
add_library(linoodle linoodle.cpp windows_api.cpp windows_library.cpp) | ||
target_link_libraries(linoodle PRIVATE pe-parse Threads::Threads) | ||
|
||
# Build tester | ||
add_executable(testlinoodle test/test.cpp) | ||
target_link_libraries(testlinoodle PRIVATE Threads::Threads ${CMAKE_DL_LIBS}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020 Will Donohoe | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# linoodle | ||
|
||
A Linux wrapper for the [Oodle Data Compression](http://www.radgametools.com/oodlecompressors.htm) library. | ||
|
||
It essentially works like this: | ||
|
||
1. Parse the Windows Oodle DLL in the current directory (`oo2core_8_win64.dll`) using the `pe-parse` library | ||
2. Map the PE into memory | ||
3. Perform relocations | ||
4. Resolve imports to point to our own implementation of the minimum set of required Windows API functions | ||
5. Setup the `gs` register to point to a fake `TIB` structure | ||
6. Execute the DLL's entry point | ||
7. Execute whatever Oodle exports you want (currently only `OodleLZ_Decompress`) | ||
|
||
## Usage | ||
|
||
When you clone this repository, make sure you use `--recurse-submodules` to get the `pe-parse` submodule. | ||
Otherwise you can run `git submodule update --init` after you've cloned it. | ||
|
||
After that, just use cmake to build the project and you'll get a `liblinoodle.so` file created in the `build` | ||
directory. You can link to this or use `dlopen`, then call the `OodleLZ_Decompress` export. | ||
|
||
``` | ||
mkdir build | ||
cd build | ||
cmake .. | ||
cd .. | ||
cmake --build build/ | ||
``` | ||
|
||
This will also build an executable which tests that the library works. Run it with `./build/testlinoodle`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
#include "windows_library.h" | ||
|
||
typedef __attribute__((ms_abi)) size_t(*tDecompressFunc)(uint8_t* srcBuf, size_t srcLen, uint8_t* dstBuf, size_t dstLen, int64_t unk1, int64_t unk2, int64_t unk3, int64_t unk4, int64_t unk5, int64_t unk6, int64_t unk7, int64_t unk8, int64_t unk9, int64_t unk10); | ||
|
||
class OodleWrapper { | ||
public: | ||
OodleWrapper() : | ||
m_oodleLib(WindowsLibrary::Load("oo2core_8_win64.dll")) | ||
{ | ||
m_decompressFunc = reinterpret_cast<tDecompressFunc>(m_oodleLib.GetExport("OodleLZ_Decompress")); | ||
} | ||
|
||
size_t Decompress(uint8_t* srcBuf, size_t srcLen, uint8_t* dstBuf, size_t dstLen, int64_t unk1, int64_t unk2, int64_t unk3, int64_t unk4, int64_t unk5, int64_t unk6, int64_t unk7, int64_t unk8, int64_t unk9, int64_t unk10) | ||
{ | ||
WindowsLibrary::SetupCall(); | ||
return m_decompressFunc(srcBuf, srcLen, dstBuf, dstLen, unk1, unk2, unk3, unk4, unk5, unk6, unk7, unk8, unk9, unk10); | ||
} | ||
|
||
private: | ||
WindowsLibrary m_oodleLib; | ||
tDecompressFunc m_decompressFunc; | ||
}; | ||
|
||
OodleWrapper g_oodleWrapper; | ||
extern "C" size_t OodleLZ_Decompress(uint8_t * srcBuf, size_t srcLen, uint8_t * dstBuf, size_t dstLen, int64_t unk1, int64_t unk2, int64_t unk3, int64_t unk4, int64_t unk5, int64_t unk6, int64_t unk7, int64_t unk8, int64_t unk9, int64_t unk10) | ||
{ | ||
return g_oodleWrapper.Decompress(srcBuf, srcLen, dstBuf, dstLen, unk1, unk2, unk3, unk4, unk5, unk6, unk7, unk8, unk9, unk10); | ||
} |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#include <fstream> | ||
#include <vector> | ||
#include <iostream> | ||
#include <string.h> | ||
#include <dlfcn.h> | ||
#include <pthread.h> | ||
|
||
typedef size_t(*tDecompressFunc)(uint8_t* srcBuf, size_t srcLen, uint8_t* dstBuf, size_t dstLen, int64_t unk1, int64_t unk2, int64_t unk3, int64_t unk4, int64_t unk5, int64_t unk6, int64_t unk7, int64_t unk8, int64_t unk9, int64_t unk10); | ||
|
||
std::vector<char> ReadAllData(const char* path) | ||
{ | ||
std::ifstream file(path, std::ios::binary | std::ios::ate); | ||
std::streamsize size = file.tellg(); | ||
file.seekg(0, std::ios::beg); | ||
std::vector<char> buffer(size); | ||
if (!file.read(buffer.data(), size)) { | ||
throw std::runtime_error("Failed to open file"); | ||
} | ||
return buffer; | ||
} | ||
|
||
void* TestFunc(void* arg) | ||
{ | ||
for (int i = 0; i < 2000; i++) | ||
{ | ||
// Load compiled library | ||
void* lib = dlopen("build/liblinoodle.so", RTLD_LAZY); | ||
if (lib == nullptr) { | ||
std::cout << "dlopen failed: " << dlerror() << std::endl; | ||
return nullptr; | ||
} | ||
auto decompress = reinterpret_cast<tDecompressFunc>(dlsym(lib, "OodleLZ_Decompress")); | ||
|
||
// Load test data | ||
auto compressedData = ReadAllData("test/compressed.data"); | ||
auto decompressedData = ReadAllData("test/decompressed.data"); | ||
|
||
for (int j = 0; j < 10; j++) | ||
{ | ||
// Decompress the data | ||
uint8_t* destBuf = reinterpret_cast<uint8_t*>(malloc(decompressedData.size() + 4096)); | ||
size_t result = decompress(reinterpret_cast<uint8_t*>(compressedData.data()), compressedData.size(), destBuf, decompressedData.size(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | ||
|
||
// Ensure it's what we expect | ||
if (result != decompressedData.size()) { | ||
std::cout << "Resulting size from OodleLZ_Decompress does not match (expected " << decompressedData.size() << ", got " << result << ")" << std::endl; | ||
return nullptr; | ||
} | ||
|
||
if (memcmp(destBuf, decompressedData.data(), decompressedData.size()) != 0) { | ||
std::cout << "Decompressed data does not match" << std::endl; | ||
return nullptr; | ||
} | ||
|
||
free(destBuf); | ||
} | ||
|
||
// Unload the library | ||
if (dlclose(lib) != 0) { | ||
std::cout << "Failed to dlclose library" << std::endl; | ||
return nullptr; | ||
} | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
int main() | ||
{ | ||
// Spin up multiple threads to run the test | ||
const int NUM_THREADS = 8; | ||
pthread_t threads[NUM_THREADS]; | ||
for (int i = 0; i < NUM_THREADS; i++) { | ||
pthread_create(&threads[i], nullptr, TestFunc, nullptr); | ||
} | ||
|
||
// Wait for the threads to finish | ||
for (int i = 0; i < NUM_THREADS; i++) { | ||
pthread_join(threads[i], nullptr); | ||
} | ||
|
||
std::cout << "Test succeeded!" << std::endl; | ||
return 0; | ||
} |
Oops, something went wrong.