Created
July 9, 2019 09:23
-
-
Save adenkiewicz/f031946a0109f37b673a837165995e40 to your computer and use it in GitHub Desktop.
PoC implementation of Alternate Data Stream browser.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <locale> | |
#include <codecvt> | |
#include <string> | |
#include <Windows.h> | |
#include <WinBase.h> | |
#include <io.h> | |
#include <fcntl.h> | |
void getADS_find(const std::wstring& filename) { | |
WIN32_FIND_STREAM_DATA fileData, streamData; | |
constexpr DWORD reserved = 0; | |
HANDLE file = FindFirstStreamW(filename.c_str(), FindStreamInfoStandard, &fileData, reserved); | |
if (file == INVALID_HANDLE_VALUE) | |
return; | |
while (FindNextStreamW(file, &streamData)) { | |
std::wcout << L"\t" << streamData.cStreamName << L"\t(size: " << streamData.StreamSize.QuadPart << L")" << std::endl; | |
} | |
} | |
namespace { | |
constexpr auto ALTERNATE_DATA_STREAM = 0x4; | |
} | |
void getADS_backup(const std::wstring& filename) { | |
HANDLE file = CreateFileW(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); | |
if (file == INVALID_HANDLE_VALUE) | |
return; | |
DWORD bytesRead = 0; | |
LPVOID ptr = nullptr; | |
WIN32_STREAM_ID streamInfo; | |
WCHAR streamName[MAX_PATH + 1]; | |
while (BackupRead(file, (LPBYTE)&streamInfo, sizeof(WIN32_STREAM_ID) - 4, &bytesRead, FALSE, FALSE, &ptr)) { | |
if (streamInfo.dwStreamId == ALTERNATE_DATA_STREAM) { | |
memset(streamName, NULL, sizeof(streamName)); | |
if (!BackupRead(file, (LPBYTE)streamName, streamInfo.dwStreamNameSize, &bytesRead, FALSE, TRUE, &ptr)) | |
break; | |
std::wcout << L"\t" << std::wstring(streamName, bytesRead) << L"\t(size: " << streamInfo.Size.QuadPart << L")" << std::endl; | |
} | |
DWORD low, high; | |
if (!BackupSeek(file, streamInfo.Size.LowPart, streamInfo.Size.HighPart, &low, &high, &ptr)) { | |
break; | |
} | |
} | |
// call ABORT on backup | |
BackupRead(file, (LPBYTE)&streamInfo, sizeof(WIN32_STREAM_ID), &bytesRead, TRUE, TRUE, &ptr); | |
} | |
int main(int argc, char *argv[]) { | |
if (argc != 2) { | |
std::cerr << "Usage: " << argv[0] << " <path to file>" << std::endl; | |
exit(-1); | |
} | |
// set console mode to handle weird UTF-16 characters | |
_setmode(_fileno(stdout), _O_U16TEXT); | |
std::wstring filename = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(argv[1]); | |
std::wcout << filename << L": // using FindFirstStream, FindNextStream" << std::endl; | |
getADS_find(filename); | |
std::wcout << std::endl; | |
std::wcout << filename << L": // using BackupRead, BackupSeek" << std::endl; | |
getADS_backup(filename); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment