First working demonware emulator

This commit is contained in:
momo5502 2022-09-21 20:59:11 +02:00
parent 1d0f79623f
commit 7c1c819a56
4 changed files with 85 additions and 40 deletions

View File

@ -17,7 +17,7 @@ Reverse engineering and analysis of Call of Duty: Black Ops 3. Very experimental
- [x] RE Tool Detection Bypass (IDA Pro, HxD, ...)
- [x] Disable Hardware Breakpoint Detection
- [x] Disable Integrity Checks
- [ ] Demonware Emulation
- [x] Demonware Emulation
- [ ] Disable Anti-Debugging Mechanisms
## Download

View File

@ -481,6 +481,10 @@ namespace demonware
utils::hook::copy_string(0x1430B93C8_g, "http://%s:%d/auth/");
utils::hook::set<uint32_t>(0x141EC4B50_g, 0xC3D08948); // Skip publisher file signature stuff
utils::hook::set<uint32_t>(0x141EC4B40_g, 0xC301B0); // FFOTD is valid
utils::hook::set<uint32_t>(0x141EBDF30_g, 0xC301B0); // DDLs available
utils::hook::set<uint32_t>(0x141E968F0_g, 0xC301B0); // QOL finished
}
void pre_destroy() override

View File

@ -72,6 +72,33 @@ namespace demonware
}
};
struct bdFileQueryResult final : public bdTaskResult
{
std::uint64_t user_id;
std::string platform;
std::string filename;
std::uint32_t errorcode;
std::string filedata;
void serialize(byte_buffer* data) override
{
data->write_uint64(user_id);
data->write_string(platform);
data->write_string(filename);
data->write_uint32(errorcode);
data->write_blob(filedata);
}
void deserialize(byte_buffer* data) override
{
data->read_uint64(&user_id);
data->read_string(&platform);
data->read_string(&filename);
data->read_uint32(&errorcode);
data->read_blob(&filedata);
}
};
class bdTimeStamp final : public bdTaskResult
{
public:

View File

@ -222,52 +222,66 @@ namespace demonware
void bdStorage::get_files(service_server* server, byte_buffer* buffer) const
{
uint32_t unk32_0;
uint32_t numfiles, count = 0;
uint64_t owner;
std::string game, platform;
std::string context;
buffer->read_string(&context);
buffer->read_string(&game);
buffer->read_uint32(&unk32_0);
buffer->read_uint64(&owner);
buffer->read_string(&platform);
buffer->read_uint64(&owner);
buffer->read_string(&platform);
buffer->read_uint32(&numfiles);
printf("demonware: ctx '%s'\n", context.data());
uint32_t count;
buffer->read_uint32(&count);
std::vector<std::pair<uint64_t, std::string>> user_ctxs;
for (auto i = 0u; i < count; i++)
{
uint64_t user_id;
std::string acc_type;
buffer->read_uint64(&user_id);
buffer->read_string(&acc_type);
printf("demonware: user 0x%llX '%s'\n", user_id, acc_type.data());
user_ctxs.emplace_back(user_id, acc_type);
}
buffer->read_uint32(&count);
std::vector<std::string> filenames;
for (auto i = 0u; i < count; i++)
{
std::string filename;
buffer->read_string(&filename);
printf("demonware: file '%s'\n", filename.data());
filenames.push_back(std::move(filename));
}
auto reply = server->create_reply(this->task_id());
uint32_t available = 0;
for (uint32_t i = 0; i < numfiles; i++)
for (size_t i = 0u; i < filenames.size(); i++)
{
std::string filename, data;
buffer->read_string(&filename);
const auto path = get_user_file_path(filename);
if (!utils::io::read_file(path, &data))
auto& name = filenames.at(i);
std::string filedata;
if (utils::io::read_file(get_user_file_path(name), &filedata))
{
#ifndef NDEBUG
printf("[DW]: [bdStorage]: get user file: missing file: %s, %s, %s\n", game.data(), filename.data(),
platform.data());
#endif
continue;
auto* entry = new bdFileQueryResult;
entry->user_id = user_ctxs.at(i).first;
entry->platform = user_ctxs.at(i).second;
entry->filename = filenames.at(i);
entry->errorcode = 0;
entry->filedata = filedata;
reply->add(entry);
available++;
std::cout << "demonware: user file '" << name << "' dispatched.\n";
}
else
{
std::cout << "demonware: user file '" << name << "' not found.\n";
}
}
auto response = new bdFile;
response->owner_id = owner;
response->unk = 0;
response->platform = platform;
response->filename = filename;
response->data = data;
reply->add(response);
++count;
#ifndef NDEBUG
printf("[DW]: [bdStorage]: get user file: %s, %s, %s\n", game.data(), filename.data(), platform.data());
#endif
}
if (count == numfiles)
if (available == count)
{
reply->send();
}