// libarchive-harness-win.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include #include // Declare function pointers for the exported functions typedef void *(*ArchiveReadNew)(); typedef int (*ArchiveReadSupportFormatAll)(void *); typedef int (*ArchiveReadOpenFilename)(void *, const char *); typedef int (*ArchiveReadNextHeader)(void *, void **); typedef int (*ArchiveReadData)(void *, void *, size_t); //(struct archive*,void*, size_t) typedef int (*ArchiveReadExtract)(void *, void *, int); // archive_read_extract(struct archive* _a, struct archive_entry* entry, int flags) typedef int (*ArchiveReadClose)(void *); typedef void (*ArchiveReadFree)(void *); #define ARCHIVE_OK 0 /* Operation was successful. */ ArchiveReadNew archive_read_new = NULL; ArchiveReadSupportFormatAll archive_read_support_format_all = NULL; ArchiveReadOpenFilename archive_read_open_filename = NULL; ArchiveReadNextHeader archive_read_next_header = NULL; ArchiveReadData archive_read_data = NULL; ArchiveReadExtract archive_read_extract = NULL; ArchiveReadClose archive_read_close = NULL; ArchiveReadFree archive_read_free = NULL; extern "C" __declspec(dllexport) int fuzzme(const char *filename); int fuzzme(const char *filename) { int result = 0; struct archive_entry *ae = {0}; char *buff[100]; // Example usage: Open an archive file void *archive = archive_read_new(); if (!archive) { std::cerr << "Error creating archive object" << std::endl; return 1; } archive_read_support_format_all(archive); if (archive_read_open_filename(archive, filename) != ARCHIVE_OK) { std::cerr << "Error opening archive file" << std::endl; archive_read_free(archive); return 1; } // Process headers and data (add your logic here) if (archive_read_next_header(archive, (void **)&ae) != ARCHIVE_OK) { std::cerr << "Error read_next_header" << std::endl; archive_read_free(archive); return 1; } if (archive_read_extract(archive, ae, 0x0002) != ARCHIVE_OK) { std::cerr << "Error read_extract" << std::endl; archive_read_free(archive); return 1; } if (result = archive_read_data(archive, buff, 99) != ARCHIVE_OK) { std::cerr << "Error read_data" << std::endl; archive_read_free(archive); return 1; } // Clean up archive_read_close(archive); archive_read_free(archive); return result; } int main(int argc, char **argv) { // inspired by https://symeonp.github.io/2017/09/17/fuzzing-winafl.html if (argc < 2) { printf("Usage: %s \n", argv[0]); return 0; } // Load the DLL you want to fuzz/test HMODULE archiveDll = LoadLibrary(L"C:\\Users\\User\\Desktop\\archiveint.dll.x64.10.0.19041.3636"); if (!archiveDll) { std::cerr << "Error loading archiveint.dll" << std::endl; return 1; } // Get function addresses archive_read_new = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_new")); archive_read_support_format_all = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_support_format_all")); archive_read_open_filename = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_open_filename")); archive_read_next_header = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_next_header")); archive_read_data = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_data")); archive_read_close = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_close")); archive_read_free = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_free")); archive_read_extract = reinterpret_cast(GetProcAddress(archiveDll, "archive_read_extract")); if (!archive_read_new || !archive_read_support_format_all || !archive_read_open_filename || !archive_read_next_header || !archive_read_data || !archive_read_close || !archive_read_free || !archive_read_extract) { std::cerr << "Error getting function addresses" << std::endl; FreeLibrary(archiveDll); return 1; } int result = fuzzme(argv[1]); std::cout << "fuzzme result: " << result << "filename: " << argv[1]; FreeLibrary(archiveDll); return 0; } // https://github.com/libarchive/libarchive/blob/master/libarchive/test/test_read_format_rar_invalid1.c // #include "test.h" // // DEFINE_TEST(test_read_format_rar_invalid1) //{ // const char* refname = "test_read_format_rar_invalid1.rar"; // struct archive* a; // struct archive_entry* ae; // char* buff[100]; // // extract_reference_file(refname); // assert((a = archive_read_new()) != NULL); // assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); // assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); // assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); // assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); // assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, 99)); // assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); // assertEqualInt(ARCHIVE_OK, archive_read_free(a)); //} ///* Extract the entries to disk. */ // assert((a = archive_read_new()) != NULL); // assertA(0 == archive_read_support_format_all(a)); // assertA(0 == archive_read_support_filter_all(a)); // assertA(0 == archive_read_open_memory(a, buff, BUFF_SIZE)); ///* Restore first entry with _EXTRACT_PERM. */ // failure("Error reading first entry"); // assertA(0 == archive_read_next_header(a, &ae)); // assertA(0 == archive_read_extract(a, ae, ARCHIVE_EXTRACT_PERM)); ///* Rest of entries get restored with no flags. */ // for (i = 1; i < numEntries; i++) { // failure("Error reading entry %d", i); // assertA(0 == archive_read_next_header(a, &ae)); // failure("Failed to extract entry %d: %s", i, // archive_entry_pathname(ae)); // assertA(0 == archive_read_extract(a, ae, 0)); // } // assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); // assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); // assertEqualInt(ARCHIVE_OK, archive_read_free(a));