payload analysis

This commit is contained in:
2026-04-22 17:19:26 +00:00
parent e75471a2d9
commit 2eb76beb1a
9 changed files with 223 additions and 29 deletions
+8
View File
@@ -0,0 +1,8 @@
# Google C/C++ Code Style Settings
Language: Cpp
BasedOnStyle: Google
Standard: c++20
IndentWidth: 2
UseTab: Never
ColumnLimit: 80
+8 -9
View File
@@ -44,20 +44,19 @@ FetchContent_Declare(
FetchContent_MakeAvailable(Encryption) FetchContent_MakeAvailable(Encryption)
# ============================================================ # ============================================================
# Target Networking # Target Test
# ============================================================ # ============================================================
file(GLOB_RECURSE SOURCES "src/*.cc") file(GLOB_RECURSE SOURCES "src/*.cc")
if (CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$") add_library(${SUB_PROJECT_NAME}_lib INTERFACE)
add_executable(${SUB_PROJECT_NAME} ${SOURCES})
else ()
add_executable(${SUB_PROJECT_NAME} ${SOURCES})
endif ()
target_link_libraries(${SUB_PROJECT_NAME} PUBLIC ${ROOT_PROJECT_NAME}::Common) target_link_libraries(${SUB_PROJECT_NAME}_lib INTERFACE ${ROOT_PROJECT_NAME}::Common)
target_link_libraries(${SUB_PROJECT_NAME} PUBLIC ${ROOT_PROJECT_NAME}::Encryption) target_link_libraries(${SUB_PROJECT_NAME}_lib INTERFACE ${ROOT_PROJECT_NAME}::Encryption)
target_include_directories(${SUB_PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(${SUB_PROJECT_NAME}_lib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
add_executable(${SUB_PROJECT_NAME} ${SOURCES})
target_link_libraries(${SUB_PROJECT_NAME} PUBLIC ${SUB_PROJECT_NAME}_lib)
# ============================================================ # ============================================================
# Compiler Options # Compiler Options
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include <cstdint>
#include <memory>
#include <span>
#include <string>
template <typename T>
struct ObjectInfo {
std::size_t GetSize() const { return sizeof(T); }
T data;
};
template <>
struct ObjectInfo<std::string> {
std::size_t GetSize() const { return data.size(); }
std::size_t SetSize(std::size_t size) {
data.resize(size);
return data.size();
}
std::string data;
};
template <>
struct ObjectInfo<std::vector<std::uint8_t>> {
std::size_t GetSize() const { return data.size(); }
std::size_t SetSize(std::size_t size) {
data.resize(size);
return data.size();
}
std::vector<std::uint8_t> data;
};
struct OLEObjectHeader {
ObjectInfo<std::uint32_t> OLEVersion;
ObjectInfo<std::uint32_t> FormatID;
ObjectInfo<std::string> ClassName;
ObjectInfo<std::string> TopicName;
ObjectInfo<std::string> ItemName;
};
struct EmbededObject {
OLEObjectHeader Header;
ObjectInfo<std::vector<std::uint8_t>> NativeData;
};
struct LinkedObject {};
struct OLEObject {
OLEObjectHeader Header;
std::unique_ptr<EmbededObject> EObject = nullptr;
std::unique_ptr<LinkedObject> LOobject = nullptr;
};
OLEObject OLEObjectParser(std::span<const std::uint8_t> data);
+3 -1
View File
@@ -1 +1,3 @@
#pragma once #pragma once
#include <vector> // IWYU pragma: export
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include <filesystem>
std::string ReadEntireFileIntoString(std::filesystem::path path);
void WriteStringToFile(std::filesystem::path path,
std::vector<std::uint8_t> data);
+11 -18
View File
@@ -1,26 +1,19 @@
#include "encryption/util/helper.h" #include "encryption/util/helper.h"
#include <fstream> #include "objects.h"
#include <iostream> #include "util/file.h"
int main() { int main() {
std::ifstream payload1_file("./payload1.txt"); std::string payload1_hex = ReadEntireFileIntoString("./payload1.txt");
if (!payload1_file) { std::string payload2_hex = ReadEntireFileIntoString("./payload2.txt");
std::cout << "파일 열기 실패\n";
return 1;
}
payload1_file.seekg(0, std::ios::end);
// 현재 위치 = 파일 크기 auto payload1 = bedrock::util::HexStrToBytes(payload1_hex);
std::streampos size = payload1_file.tellg(); auto payload2 = bedrock::util::HexStrToBytes(payload2_hex);
std::string payload1; // OLEObject obj1 = OLEObjectParser(payload1);
payload1.resize(size); OLEObject obj2 = OLEObjectParser(payload2);
payload1_file >> payload1;
// payload1_file.read(payload1.data(), size);
std::cout << "red: " << payload1 << std::endl; WriteStringToFile("./payload1.bin", payload1);
WriteStringToFile("./payload2.bin", payload2);
auto bytes = bedrock::util::HexStrToBytes(payload1);
return 0; return 0;
} }
+95
View File
@@ -0,0 +1,95 @@
#include "objects.h"
#include <cstring>
#include <memory>
static void OLEObjectHeaderParser(OLEObjectHeader& object,
std::span<const std::uint8_t> data,
std::size_t& read_offset) {
const std::uint8_t* data_ptr = data.data();
std::uint32_t size = 0;
// OLE vsersion data must be ignored
std::memcpy(&object.OLEVersion.data, data_ptr + read_offset,
object.OLEVersion.GetSize());
read_offset += 4;
std::memcpy(&object.FormatID.data, data_ptr + read_offset,
object.FormatID.GetSize());
read_offset += 4;
// Read LengthPrefixedAnsiString (ClassName)
std::memcpy(&size, data_ptr + read_offset, 4);
read_offset += 4;
object.ClassName.SetSize(size);
std::memcpy(object.ClassName.data.data(), data_ptr + read_offset,
object.ClassName.GetSize());
read_offset += object.ClassName.GetSize();
// Read LengthPrefixedAnsiString (TopicName)
std::memcpy(&size, data_ptr + read_offset, 4);
read_offset += 4;
object.TopicName.SetSize(size);
std::memcpy(object.TopicName.data.data(), data_ptr + read_offset,
object.TopicName.GetSize());
read_offset += object.TopicName.GetSize();
// Read LengthPrefixedAnsiString (ItemName)
std::memcpy(&size, data_ptr + read_offset, 4);
read_offset += 4;
object.ItemName.SetSize(size);
std::memcpy(object.ItemName.data.data(), data_ptr + read_offset,
object.ItemName.GetSize());
read_offset += object.ItemName.GetSize();
return;
}
static void OLEObjectLinkedObjectParser(OLEObject& object,
std::span<const std::uint8_t> data,
std::size_t& read_offset) {
// Not Implemented
return;
}
static void OLEObjectEnbeddedObjectParser(OLEObject& object,
std::span<const std::uint8_t> data,
std::size_t& read_offset) {
object.EObject = std::make_unique<EmbededObject>();
const std::uint8_t* data_ptr = data.data();
std::uint32_t size = 0;
// Intentionally ignore 2nd header parsing (which is NOT in spec)
// OLEObjectHeaderParser(object.EObject->Header, data, read_offset);
// Read NativeDataSize
std::memcpy(&size, data_ptr + read_offset, 4);
read_offset += 4;
object.EObject->NativeData.SetSize(size);
std::memcpy(object.EObject->NativeData.data.data(), data_ptr + read_offset,
object.EObject->NativeData.GetSize());
read_offset += object.EObject->NativeData.GetSize();
return;
}
// Please refer to MS-OLEDS spec and MS-CFB spec
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-oleds/85583d21-c1cf-4afe-a35f-d6701c5fbb6f
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/53989ce4-7b05-4f8d-829b-d08d6148375b
OLEObject OLEObjectParser(std::span<const std::uint8_t> data) {
OLEObject object;
std::size_t read_offset = 0;
OLEObjectHeaderParser(object.Header, data, read_offset);
if (object.Header.FormatID.data == 0x00000001) {
OLEObjectLinkedObjectParser(object, data, read_offset);
} else if (object.Header.FormatID.data == 0x00000002) {
OLEObjectEnbeddedObjectParser(object, data, read_offset);
} else {
// invalid object
return {};
}
return object;
}
+34
View File
@@ -0,0 +1,34 @@
#include "util/file.h"
#include <fstream>
std::string ReadEntireFileIntoString(std::filesystem::path path) {
std::ifstream file(path);
if (!file) {
return {};
}
file.seekg(0, std::ios::end);
// 현재 위치 = 파일 크기
std::size_t size = static_cast<std::size_t>(file.tellg());
file.seekg(0, std::ios::beg);
std::string contents;
contents.resize(size);
file.read(contents.data(), static_cast<std::streamsize>(size));
return contents;
}
void WriteStringToFile(std::filesystem::path path,
std::vector<std::uint8_t> data) {
std::ofstream file(path, std::ios::binary);
if (!file) {
return;
}
file.write(reinterpret_cast<const char*>(data.data()),
static_cast<std::streamsize>(data.size()));
return;
}
+1 -1
View File
@@ -3,7 +3,7 @@ file(GLOB TEST_SOURCES "*.cc")
foreach(test_src ${TEST_SOURCES}) foreach(test_src ${TEST_SOURCES})
get_filename_component(test_name ${test_src} NAME_WE) get_filename_component(test_name ${test_src} NAME_WE)
add_executable(${test_name} ${test_src}) add_executable(${test_name} ${test_src})
target_link_libraries(${test_name} PRIVATE ${PROJECT_NAME}) target_link_libraries(${test_name} PRIVATE ${PROJECT_NAME}_lib)
if(NOT WIN32) if(NOT WIN32)
target_compile_options(${test_name} PRIVATE -fno-exceptions -march=native -maes -msse2 -msse3 -mssse3 -msse4.1 -msse4.2) target_compile_options(${test_name} PRIVATE -fno-exceptions -march=native -maes -msse2 -msse3 -mssse3 -msse4.1 -msse4.2)
endif() endif()