Skip to content

Commit

Permalink
Add a tlv_server to demonstrate a multi-packet target (#71)
Browse files Browse the repository at this point in the history
This PR adds a `tlv_server` highly inspired from @y0ny0ns0n's - I've C++ified it and remove a few bugs. I've also added both the `hevd_client` as part of the Windows solution as well. (#69)
  • Loading branch information
0vercl0k authored Feb 4, 2022
1 parent 8a133c1 commit 942db63
Show file tree
Hide file tree
Showing 9 changed files with 578 additions and 341 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/wtf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ jobs:
src/build/symsrv.dll
Linux:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler: ['clang', 'gcc']

name: Ubuntu 20.04 / ${{ matrix.compiler }}
name: Ubuntu latest / ${{ matrix.compiler }}
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
10 changes: 10 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ if (WIN32)
delayimp.lib
bcrypt.lib
)

add_executable(
tlv_server
tlv_server/tlv_server.cc
)

add_executable(
hevd_client
hevd_client/hevd_client.cc
)
else (WIN32)
enable_language(ASM)
find_package(Threads)
Expand Down
26 changes: 26 additions & 0 deletions src/hevd_client/hevd_client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Axel '0vercl0k' Souchet - July 10 2021
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <array>
#include <cstdio>

int main() {
HANDLE H =
CreateFileA(R"(\\.\GLOBALROOT\Device\HackSysExtremeVulnerableDriver)",
GENERIC_ALL, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if (H == INVALID_HANDLE_VALUE) {
printf("CreateFileA failed, bailing.\n");
return EXIT_FAILURE;
}

std::array<uint8_t, 1024> Buffer;
if (getenv("BREAK") != nullptr) {
__debugbreak();
}

DWORD Returned = 0;
DeviceIoControl(H, 0xdeadbeef, Buffer.data(), Buffer.size(), Buffer.data(),
Buffer.size(), &Returned, nullptr);
CloseHandle(H);
return EXIT_SUCCESS;
}
197 changes: 197 additions & 0 deletions src/tlv_server/tlv_server.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// y0ny0ns0n / Axel '0vercl0k' Souchet - February 1 2022
#include <algorithm>
#include <cinttypes>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib, "ws2_32.lib")

enum class Command_t : uint32_t { Allocate, Edit, Delete };

struct CommonPacketHeader_t {
Command_t CommandId;
uint32_t ChunkId;
uint32_t BodySize;
};

struct Chunk_t {
uint32_t Id;
int32_t Size;
std::unique_ptr<uint8_t[]> Buf;
};

std::unique_ptr<Chunk_t> ChunkList[4] = {};

void ProcessPacket(const uint8_t *Packet, const uint32_t PacketSize) {
auto Header = (CommonPacketHeader_t *)Packet;

if (PacketSize < sizeof(*Header)) {
printf("[!] Packet is not big enough to check the header\n");
return;
}

if (Header->BodySize != (PacketSize - sizeof(*Header))) {
printf("[!] Body size is not accurate\n");
return;
}

const auto CommandId = Header->CommandId;
const auto Body = (uint8_t *)(Header + 1);
printf("[+] CommandId = %d\n", CommandId);

switch (CommandId) {
case Command_t::Allocate: {
const auto &ChunkId = Header->ChunkId;
const auto &FreeChunkPtr =
std::find_if(ChunkList, std::end(ChunkList),
[&](const auto &Entry) { return Entry == nullptr; });

#ifdef PATCHED
if (FreeChunkPtr == std::end(ChunkList)) {
printf("[!] there's no available slot.\n");
return;
}
#endif

auto Chunk = std::make_unique<Chunk_t>();
Chunk->Id = ChunkId;
Chunk->Size = Header->BodySize;
Chunk->Buf = std::make_unique<uint8_t[]>(Chunk->Size);
memcpy(Chunk->Buf.get(), Body, Chunk->Size);
*FreeChunkPtr = std::move(Chunk);
break;
}

case Command_t::Edit: {
const auto &ChunkId = Header->ChunkId;
const auto &MatchingChunkPtr = std::find_if(
std::begin(ChunkList), std::end(ChunkList), [&](const auto &Entry) {
return Entry != nullptr && Entry->Id == ChunkId;
});

if (MatchingChunkPtr == std::end(ChunkList)) {
printf("[!] Couldn't find ChunkId 0x%" PRIx32 "\n", ChunkId);
return;
}

auto MatchingChunk = MatchingChunkPtr->get();
const uint32_t NewBufSize = Header->BodySize;

if (NewBufSize > MatchingChunk->Size) {
MatchingChunk->Buf = std::make_unique<uint8_t[]>(NewBufSize);
MatchingChunk->Size = NewBufSize;
}

memcpy(MatchingChunk->Buf.get(), Body, NewBufSize);
break;
}

case Command_t::Delete: {
const auto &ChunkId = Header->ChunkId;
const auto &MatchingChunkPtr = std::find_if(
std::begin(ChunkList), std::end(ChunkList), [&](const auto &Entry) {
return Entry != nullptr && Entry->Id == ChunkId;
});

if (MatchingChunkPtr == std::end(ChunkList)) {
printf("[!] Couldn't find ChunkId 0x%" PRIx32 "\n", ChunkId);
return;
}

MatchingChunkPtr->reset();
break;
}
}
}

struct WSAInitializer_t {
WSADATA Wsa = {};
WSAInitializer_t() {
if (WSAStartup(MAKEWORD(2, 2), &Wsa) != 0) {
std::abort();
}
}

~WSAInitializer_t() { WSACleanup(); }
} WsaData;

static WSAInitializer_t WSAInitializer;

int main() {
// Highly inspired from:
// https://docs.microsoft.com/en-us/windows/win32/winsock/complete-server-code

SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("[!] socket failed, WSA GLE = 0x%08x\n", WSAGetLastError());
return EXIT_FAILURE;
}

struct sockaddr_in LoopbackAddr = {};
const uint16_t ListenPort = 4444;
LoopbackAddr.sin_family = AF_INET;
LoopbackAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
LoopbackAddr.sin_port = htons(ListenPort);
if (bind(ListenSocket, (sockaddr *)&LoopbackAddr, sizeof(LoopbackAddr)) ==
SOCKET_ERROR) {
printf("[!] bind failed, WSA GLE = 0x%08x\n", WSAGetLastError());
closesocket(ListenSocket);
return EXIT_FAILURE;
}

printf("[+] Listening on tcp:%" PRIu16 "...\n", ListenPort);
if (listen(ListenSocket, 1) == SOCKET_ERROR) {
printf("[!] listen failed, WSA GLE = 0x%08x\n", WSAGetLastError());
closesocket(ListenSocket);
return EXIT_FAILURE;
}

SOCKET ClientSocket = accept(ListenSocket, nullptr, nullptr);
if (ClientSocket == INVALID_SOCKET) {
printf("[!] accept failed, WSA GLE = 0x%08x\n", WSAGetLastError());
closesocket(ListenSocket);
return EXIT_FAILURE;
}

printf("[+] accept done!\n");

while (1) {
uint32_t BufferSize = 0;
int Received =
recv(ClientSocket, (char *)&BufferSize, sizeof(BufferSize), 0);

if (Received != sizeof(BufferSize)) {
printf("[!] recv failed or didn't receive enough, WSA GLE = 0x%08x\n",
WSAGetLastError());
break;
}

if (BufferSize == 0 || BufferSize >= 0x4'00) {
printf("[!] BufSize(0x%" PRIx32 ") too big, skipping\n ", BufferSize);
continue;
}

auto Buffer = std::make_unique<uint8_t[]>(BufferSize);
printf("[+] BufferSize = %" PRIx32 "\n", BufferSize);

Received = recv(ClientSocket, (char *)Buffer.get(), BufferSize, 0);

if (Received != BufferSize) {
printf("recv failed, WSA GLE = 0x%08x\n", WSAGetLastError());
break;
}

ProcessPacket(Buffer.get(), BufferSize);
}

for (auto &Chunk : ChunkList) {
Chunk.reset();
}

closesocket(ClientSocket);
return EXIT_SUCCESS;
}
4 changes: 1 addition & 3 deletions src/wtf/fuzzer_hevd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,10 @@ bool Init(const Options_t &Opts, const CpuState_t &) {
return true;
}

bool Restore() { return true; }

//
// Register the target.
//

Target_t Hevd("hevd", Init, InsertTestcase, Restore, NULL, NULL);
Target_t Hevd("hevd", Init, InsertTestcase);

} // namespace Hevd
Loading

0 comments on commit 942db63

Please sign in to comment.