payload analysis
This commit is contained in:
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -1 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector> // IWYU pragma: export
|
||||||
|
|||||||
@@ -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);
|
||||||
+10
-17
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user