Skip to content

Commit

Permalink
better hash supports with crack tools, some dump tools and wip new vm…
Browse files Browse the repository at this point in the history
… support
  • Loading branch information
ate47 committed Aug 8, 2024
1 parent bd4c06f commit da6b761
Show file tree
Hide file tree
Showing 18 changed files with 1,521 additions and 124 deletions.
12 changes: 6 additions & 6 deletions release/RELEASE.MD
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
- tools
- mwiii cordycep dump tool
- luafile, gscobj, localize, ddl, scriptbundle, stringtable dump
- gsc compiler
- gsc compiler
- ?. and ?? operators
- is syntax
- ignore #region in preprocessor
- bo3 compilers
- fix includes
- gsc decompiler
- gsc decompiler
- better serious/xensik syntax
- read dev strings
- write debug data
- use debug data in decompilation
- gfx world dump
- bo3 injector
- colors in logs
- more dbf assets
- gfx world dump
- bo3 injector
- colors in logs
- more dbf assets
- tools ui
- use vm name in bad injection
- bo4 dll
Expand Down
8 changes: 7 additions & 1 deletion src/acts/actscli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ namespace {
const char* output = "acts.acpf";

std::unordered_set<uint16_t> vms{};
std::unordered_set<byte> vmsAny{};

if (argc > 2) {
output = argv[2];
Expand Down Expand Up @@ -220,12 +221,16 @@ namespace {
}

vms.insert(utils::CatLocated16(plt, vm));
vmsAny.insert((byte)vm);
}
}

auto doPackVm = [&vms](byte vm, tool::gsc::opcode::Platform plt) {
return vms.empty() || vms.contains(utils::CatLocated16(plt, vm)) || vms.contains(utils::CatLocated16(0, vm));
};
auto doPackAnyVm = [&vmsAny](byte vm) {
return vmsAny.empty() || vmsAny.contains((byte)vm);
};

// read maps
hashutils::ReadDefaultFile();
Expand Down Expand Up @@ -304,6 +309,7 @@ namespace {

size_t vmIdx{};
for (const auto& [vm, vminfo] : vmmap) {
if (!doPackAnyVm(vm)) continue;
auto stroff = AppendString(vminfo.name);

uint32_t platformCount{};
Expand Down Expand Up @@ -360,7 +366,7 @@ namespace {
vmv.platformsOffset = plts;
}

reinterpret_cast<ActsPack*>(packFileData.data())->vmCount = (uint32_t)vmmap.size();
reinterpret_cast<ActsPack*>(packFileData.data())->vmCount = (uint32_t)vmIdx;
reinterpret_cast<ActsPack*>(packFileData.data())->vmOffset = vmoffset;

LOG_INFO("Done.");
Expand Down
49 changes: 48 additions & 1 deletion src/acts/hashutils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <includes.hpp>
#include "actscli.hpp"
#include "compatibility/scobalula_wni.hpp"
#include <rapidcsv.h>

namespace {
std::unordered_map<uint64_t, std::string> g_hashMap{};
std::set<uint64_t> g_extracted{};
Expand Down Expand Up @@ -34,6 +36,48 @@ void hashutils::ReadDefaultFile() {
})) {
LOG_ERROR("Error when reading WNI files");
};

std::vector<std::filesystem::path> csvs{};

utils::GetFileRecurse(wniPackageIndex, csvs, [](const std::filesystem::path& p) {
auto s = p.string();
return s.ends_with(".hash.csv");
});

for (const std::filesystem::path& csv : csvs) {
LOG_DEBUG("Reading HASH CSV {}", csv.string());
std::string buffer{};

if (!utils::ReadFile(csv, buffer)) {
LOG_WARNING("Can't read hash csv {}", csv.string());
continue;
}

rapidcsv::Document doc{};

std::stringstream stream{ buffer };

doc.Load(stream, rapidcsv::LabelParams(-1, -1), rapidcsv::SeparatorParams(','));

if (doc.GetColumnCount() < 2) {
LOG_WARNING("Can't read hash csv {}: invalid file", csv.string());
continue;
}

for (size_t i = 0; i < doc.GetRowCount(); i++) {
const std::string hash = doc.GetCell<std::string>(0, i);
const std::string value = doc.GetCell<std::string>(1, i);

try {
AddPrecomputed(std::strtoull(hash.c_str(), nullptr, 16), value.c_str());
}
catch (std::runtime_error& e) {
LOG_WARNING("Error when reading {}: invalid line {}: {}", csv.string(), i, e.what());
}
}

}

}

show0 = opt.show0Hash;
Expand Down Expand Up @@ -202,13 +246,16 @@ int hashutils::LoadMap(const char* file, bool ignoreCol, bool iw) {
LOG_TRACE("End load hash file {} -> {}", file, count);
return issues;
}

bool hashutils::Add(const char* str, bool ignoreCol, bool iw) {
g_hashMap.emplace(hashutils::Hash64(str), str);
if (iw) {
g_hashMap.emplace(hashutils::HashIW(str), str);
g_hashMap.emplace(hashutils::HashIW2(str), str);
g_hashMap.emplace(hashutils::Hash64(str, 0x811C9DC5, 0x1000193) & 0xFFFFFFFF, str);
uint64_t sv = hashutils::HashIWDVar(str) & 0x7FFFFFFFFFFFFFFF;
uint64_t sf = hashutils::HashT10Scr(str) & 0x7FFFFFFFFFFFFFFF;
if (sv) g_hashMap.emplace(sv, str);
if (sf) g_hashMap.emplace(sf, str);
return true;
}
bool cand32 = true;
Expand Down
42 changes: 21 additions & 21 deletions src/acts/hashutils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,6 @@ namespace hashutils {
* @return the size of the hash map
*/
size_t Size();

/*
* Compute the hash32 on a string (canon id)
* @param str String to compute
* @return hashed value
*/
constexpr uint32_t Hash32(const char* str) { return hash::Hash32(str); }
/*
* Compute the hash64 on a string (fnva1), path are unformatted
* @param str String to compute
* @param start Start value, can be a previous hash to concatenate hashes
* @return Hashed value
*/
constexpr uint64_t Hash64(const char* str, uint64_t start = 0xcbf29ce484222325LL, uint64_t iv = 0x100000001b3) { return hash::Hash64(str, start, iv); }
constexpr uint64_t HashIW(const char* str) { return hash::Hash64(str, 0x47F5817A5EF961BA); }
constexpr uint64_t HashIW2(const char* str) { return hash::Hash64(str, 0x79D6530B0BB9B5D1, 0x10000000233); }
constexpr uint64_t Hash64A(const char* str, uint64_t start = 0xcbf29ce484222325LL, uint64_t iv = 0x100000001b3) { return hash::Hash64A(str, start, iv); }
constexpr uint64_t HashAIW(const char* str) { return hash::Hash64A(str, 0x47F5817A5EF961BA); }
constexpr uint64_t HashAIW2(const char* str) { return hash::Hash64A(str, 0x79D6530B0BB9B5D1, 0x10000000233); }
constexpr uint32_t HashT7(const char* str) { return (uint32_t)(hash::Hash64A(str, 0x4B9ACE2F, 0x1000193) & 0xFFFFFFFF) * 0x1000193; }

/*
* Compute the hash32 on a string (canon id), but allow pattern like "function_123456"
* @param str String to compute
Expand All @@ -130,4 +109,25 @@ namespace hashutils {
* @return Hashed value
*/
inline uint64_t Hash64Pattern(const char* str) { return hash::Hash64Pattern(str); }

constexpr uint64_t HashSecure(const char* pattern, uint64_t start, const char* str, uint64_t iv) {
if (!str || !*str) {
return 0;
}

uint64_t base = hash::Hash64A(pattern, (start ^ *str) * iv, iv);
return hash::Hash64A(str + 1, base, iv);
}

constexpr uint32_t Hash32(const char* str) { return hash::Hash32(str); }
constexpr uint64_t Hash64(const char* str, uint64_t start = 0xcbf29ce484222325LL, uint64_t iv = 0x100000001b3) { return hash::Hash64(str, start, iv); }
constexpr uint64_t HashIW(const char* str, uint64_t start = 0x47F5817A5EF961BA) { return hash::Hash64(str, start); }
constexpr uint64_t HashIW2(const char* str, uint64_t start = 0x79D6530B0BB9B5D1) { return hash::Hash64(str, start, 0x10000000233); }
constexpr uint64_t HashIWTag(const char* str, uint64_t start = 0x811C9DC5) { return hash::Hash64(str, start, 0x1000193) & 0xFFFFFFFF; }
constexpr uint64_t Hash64A(const char* str, uint64_t start = 0xcbf29ce484222325LL, uint64_t iv = 0x100000001b3) { return hash::Hash64A(str, start, iv); }
constexpr uint64_t HashAIW(const char* str, uint64_t start = 0x47F5817A5EF961BA) { return hash::Hash64A(str, start); }
constexpr uint64_t HashAIW2(const char* str, uint64_t start = 0x79D6530B0BB9B5D1) { return hash::Hash64A(str, start, 0x10000000233); }
constexpr uint32_t HashT7(const char* str) { return (uint32_t)(hash::Hash64A(str, 0x4B9ACE2F, 0x1000193) & 0xFFFFFFFF) * 0x1000193; }
constexpr uint64_t HashIWDVar(const char* str, uint64_t start = 0) { return !start ? HashSecure("q6n-+7=tyytg94_*", 0xD86A3B09566EBAAC, str, 0x10000000233) : hash::Hash64A(str, start, 0x10000000233); }
constexpr uint64_t HashT10Scr(const char* str, uint64_t start = 0) { return !start ? HashSecure("zt@f3yp(d[kkd=_@", 0x1C2F2E3C8A257D07, str, 0x10000000233) : hash::Hash64A(str, start, 0x10000000233); }
}
17 changes: 17 additions & 0 deletions src/acts/tools/bo6/bo6.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

namespace bo6 {

enum T10ScrVarType : uint32_t {
T10VT_INTEGER = 6,
T10VT_HASH = 9,
T10VT_RESOURCE_HASH = 10,
T10VT_DVAR_HASH = 11,
T10VT_TAG_HASH = 12,
T10VT_TARGET_HASH = 13,
T10VT_BUILTIN_FUNCTION = 17,
T10VT_BUILTIN_METHOD = 18,
T10VT_ANIMATION = 20,

};
}
113 changes: 113 additions & 0 deletions src/acts/tools/bo6/bo6ps4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include <includes.hpp>
#include "tools/dump.hpp"
#include "tools/gsc.hpp"
#include <pool.hpp>
#include "tools/bo6/bo6.hpp"

namespace {

int ps4dumpbo6(Process& _, int argc, const char* argv[]) {
if (argc < 3) {
return tool::BAD_USAGE;
}

const char* ipd = argv[2];

libdebug::PS4DBG ps4{ ipd };
try {
ps4.Connect();



auto procList = ps4.GetProcessList();
auto proc = procList.FindProcess("eboot.bin");

if (!proc) {
ps4.Notify(222, "Please start the game");
LOG_ERROR("Can't find eboot.bin");
ps4.Disconnect();
return tool::BASIC_ERROR;
}

auto pid = proc->pid;

auto entries = ps4.GetProcessMaps(proc->pid);

uint64_t base = 0;

for (const auto& entry : entries.entries) {
if (entry->prot == 5) {
LOG_INFO("executable base : 0x{:x}", entry->start);
base = entry->start;
break;
}
}

if (!base) {
LOG_ERROR("Can't find executable base");
ps4.Disconnect();
return tool::BASIC_ERROR;
}
struct DB_AssetPool
{
uintptr_t m_entries; // void*
uintptr_t m_freeHead; // void*
unsigned int m_poolSize;
unsigned int m_elementSize;
unsigned int m_loadedPoolSize;
char __padding[158];
};

uintptr_t poolIdx = base + 0x98FEFA0 + sizeof(DB_AssetPool) * 69; // 69 = gscobj
auto bytes = ps4.ReadMemory(pid, poolIdx, sizeof(DB_AssetPool));

auto* pool = reinterpret_cast<DB_AssetPool*>(bytes.data());

struct GscObjEntry {
uint64_t name;
int len;
int padc;
uintptr_t buffer;
};

LOG_INFO("Pool: {:x}, count: {}/{}, len 0x{:x}", pool->m_entries, pool->m_loadedPoolSize, pool->m_poolSize, pool->m_elementSize);
auto bytes2 = ps4.ReadMemory(pid, pool->m_entries, sizeof(GscObjEntry) * pool->m_loadedPoolSize);

auto* objs = reinterpret_cast<GscObjEntry*>(bytes2.data());

std::filesystem::path gsc = "gsc";

std::filesystem::create_directories(gsc);

for (size_t i = 0; i < pool->m_loadedPoolSize; i++) {
auto& obj = objs[i];

if (!obj.len || !obj.buffer) {
LOG_WARNING("Ignore {:x}", obj.name);
continue;
}

auto bytes3 = ps4.ReadMemory(pid, obj.buffer, obj.len);

if (!utils::WriteFile(gsc / utils::va("script_%llx.gscc", obj.name), bytes3.data(), bytes3.size())) {
LOG_ERROR("Error when writting {:x}", obj.name);
}
else {
LOG_INFO("Dump script_{:x}.gscc", obj.name);
}

}

ps4.Notify(210, "test");
}
catch (const char* res) {
LOG_ERROR("{}", res);
}
ps4.Disconnect();

return tool::OK;
}


ADD_TOOL("ps4dumpbo6", "dev", " [ip:port]", "", nullptr, ps4dumpbo6);
}
2 changes: 1 addition & 1 deletion src/acts/tools/coder/error_coder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1957,7 +1957,7 @@ namespace {
tool::ui::window().SetTitleFont(info.titleLabel);
}
}
ADD_TOOL_UI("errenc", L"Error encoder", Render, Update, Resize);
ADD_TOOL_UI("errenc", L"T8/9 Error encoder", Render, Update, Resize);

ADD_TOOL("errenc", "hash", "[error]", "encode an error", nullptr, errenc);
ADD_TOOL("errdec", "hash", "[w1] [w2] [w3] [w4]", "decode an error", nullptr, errdec);
Loading

0 comments on commit da6b761

Please sign in to comment.