Last active
December 4, 2024 03:15
-
-
Save odzhan/56eb105a611dcdebd1d3a084c7312190 to your computer and use it in GitHub Desktop.
Revisions
-
odzhan revised this gist
Jan 1, 2024 . 1 changed file with 48 additions and 29 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -36,9 +36,33 @@ #define PACKET_COMPR_TYPE_RDP8 4 // MSDN references this, but I doubt it's actually supported by OS #define PACKET_ENCRYPTED 0x10 // Indicates that RDP 5.0 bulk compression (see [MS-RDPBCGR] section 3.1.8.4.2) was used. //#define PACKET_COMPR_TYPE_64K 0x01 // The data in the MatchCount, MatchDetails, and Literals fields has been compressed with the level-2 compressor. #define PACKET_COMPRESSED 0x20 // The decompressed data MUST be placed at the beginning of the level-2 history buffer. #define PACKET_AT_FRONT 0x40 // The level-2 history buffer MUST be reinitialized (by filling it with zeros). #define PACKET_FLUSHED 0x80 // The level-1 history buffer MUST be reinitialized (by filling it with zeros). #define L1_PACKET_AT_FRONT 0x04 // No compression was performed. In this case, the MatchCount and MatchDetails fields MUST NOT be present. // The Literals field MUST be present. #define L1_NO_COMPRESSION 0x02 // Compression with the level-1 compressor was performed and the MatchCount // and MatchDetails fields MUST be present and contain at least one match. The Literals field MUST also be present. #define L1_COMPRESSED 0x01 // Indicates that additional level-2 compression has been performed on the level-1 compressor output // and that the Level2ComprFlags /field contains valid data and MUST be processed. #define L1_INNER_COMPRESSION 0x10 // ****************************************************** // Needed to allocate memory for compression context. @@ -51,10 +75,10 @@ void (WINAPI *_RDPCompress_InitSendContext)(void *ctx, SIZE_T ctx_len, DWORD Com // Compress inbuf and store in outbuf typedef BYTE (WINAPI *_RDPCompress)(DWORD ComprType, void *inbuf, void *outbuf, PDWORD outlen, void *ctx); typedef BYTE (WINAPI *_RDPCompressEx)(DWORD opt, void *inbuf, DWORD inlen, void *outbuf, PDWORD outlen, void *ctx); // ****************************************************** typedef @@ -91,17 +115,20 @@ typedef struct _RDP_pack_ctx { std::vector<BYTE> inbuf, outbuf; } RDP_pack_ctx; #define RDP_COMPR_BLK_LEN (8192 * 4) #pragma pack(push, 1) typedef struct _RDP_pack_blk { WORD flags; WORD len; BYTE data[RDP_COMPR_BLK_LEN + 12]; } RDP_pack_blk; #pragma pack(pop) bool init_pack_ctx(RDP_pack_ctx *c) { printf("%zd\n", sizeof(RDP_pack_blk) - (RDP_COMPR_BLK_LEN + 12)); HMODULE rdpbase = LoadLibrary("rdpbase.dll"); if (!rdpbase) return false; @@ -145,14 +172,14 @@ WriteFileData(std::string path, std::vector<BYTE> data) { BOOL rdp_encode(RDP_pack_ctx *c) { void *SendCtx = NULL; BOOL result = TRUE; do { DWORD ctx_len = c->RDPCompress_GetContextSize(c->type); if (!ctx_len) { result = FALSE; break; } SendCtx = malloc(ctx_len); if (!SendCtx) { result = FALSE; break; } c->RDPCompress_InitSendContext(SendCtx, ctx_len, c->type); @@ -166,17 +193,20 @@ rdp_encode(RDP_pack_ctx *c) { // 12 bytes are needed for header/flags in.len = inlen > c->blk - 12 ? c->blk - 12: inlen; DWORD outlen = c->blk; memcpy(in.data, inbuf, in.len); out.flags = c->RDPCompressEx(c->type, in.data, in.len, out.data, &outlen, SendCtx); if (!out.flags) { printf("RDPCompressEx failed for block %ld, %ld\n", cnt, in.len); result = FALSE; break; } out.len = outlen & 0xFFFF; //printf("flags=%02X Block : %ld (%ld -> %ld) bytes...\n", out.flags, cnt, in.len, out.len); c->outbuf.insert(c->outbuf.end(), (PBYTE)&out, (PBYTE)&out + out.len + sizeof(DWORD)); inlen -= in.len; @@ -217,26 +247,15 @@ rdp_decode(RDP_pack_ctx *c) { result = c->RDPDecompress( in->data, in->len, in->flags & PACKET_AT_FRONT, (PVOID*)&outbuf, &outlen, RecvContext, c->type); if (!result) { printf("RDPDecompress() failed for block %ld, %ld -> %ld\n", cnt, in->len, outlen); break; } //printf("Saving %ld bytes for block %ld...\n", outlen, cnt); -
odzhan revised this gist
Jan 1, 2024 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ /** Compression using undocumented API in rdpbase.dll RDPCompressEx supports four algorithms : MPPC-8K, MPPC-64K, NCRUSH and XCRUSH. This code supports all except NCRUSH. The MPPC compression ratio is very similar to LZSS, so this could be quite useful for shellcode trying to evade detection. -
odzhan revised this gist
Jan 1, 2024 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -145,7 +145,7 @@ WriteFileData(std::string path, std::vector<BYTE> data) { BOOL rdp_encode(RDP_pack_ctx *c) { void *SendCtx = NULL; BOOL result = FALSE; do { DWORD ctx_len = c->RDPCompress_GetContextSize(c->type); @@ -183,7 +183,7 @@ rdp_encode(RDP_pack_ctx *c) { inbuf += in.len; cnt++; } } while (0); if (SendCtx) free(SendCtx); return result; @@ -195,7 +195,7 @@ rdp_encode(RDP_pack_ctx *c) { BOOL rdp_decode(RDP_pack_ctx *c) { void *RecvContext = NULL; BOOL result = FALSE; do { DWORD ctx_len = c->RDPDeCompress_GetContextSize(c->type); @@ -246,7 +246,7 @@ rdp_decode(RDP_pack_ctx *c) { inbuf += in->len + sizeof(DWORD); cnt++; } } while (0); if (RecvContext) free(RecvContext); return result; -
odzhan revised this gist
Jan 1, 2024 . 1 changed file with 108 additions and 77 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -4,21 +4,14 @@ RDPCompress supports four algorithms : MPPC-8K, MPPC-64K, NCRUSH and XCRUSH. This code supports all except NCRUSH. The MPPC compression ratio is very similar to LZSS, so this could be quite useful for shellcode trying to evade detection. NCRUSH compression appears to work but fails for decompression. cl /EHsc rdp_pack.cpp compress: rdp_pack e0 infile outfile.8k decompress: rdp_pack d0 infile.8k outfile */ #include <windows.h> @@ -35,30 +28,6 @@ #include <sstream> #include <iomanip> // type of compression #define PACKET_COMPR_TYPE_8K 0 // MPPC #define PACKET_COMPR_TYPE_64K 1 // MPPC @@ -84,6 +53,9 @@ void (WINAPI *_RDPCompress_InitSendContext)(void *ctx, SIZE_T ctx_len, DWORD Com typedef DWORD (WINAPI *_RDPCompress)(DWORD ComprType, void *inbuf, void *outbuf, PDWORD outlen, void *ctx); typedef DWORD (WINAPI *_RDPCompressEx)(DWORD opt, void *inbuf, DWORD inlen, void *outbuf, PDWORD outlen, void *ctx); // ****************************************************** typedef DWORD (WINAPI *_RDPDeCompress_GetContextSize)(DWORD ComprType); @@ -92,7 +64,7 @@ typedef void (WINAPI *_RDPCompress_InitRecvContext)(void *ctx, SIZE_T ctx_len, DWORD ComprType, void *workspace); typedef BOOL (WINAPI *_RDPDecompress)( PVOID inbuf, DWORD inlen, DWORD start, @@ -104,10 +76,13 @@ DWORD (WINAPI *_RDPDecompress)( typedef struct _RDP_pack_ctx { DWORD type; // compression algorithm PCHAR name; DWORD blk; _RDPCompress_GetContextSize RDPCompress_GetContextSize; _RDPCompress_InitSendContext RDPCompress_InitSendContext; _RDPCompress RDPCompress; // doesn't work with XCRUSH _RDPCompressEx RDPCompressEx; _RDPDeCompress_GetContextSize RDPDeCompress_GetContextSize; _RDPCompress_InitRecvContext RDPCompress_InitRecvContext; @@ -116,12 +91,12 @@ typedef struct _RDP_pack_ctx { std::vector<BYTE> inbuf, outbuf; } RDP_pack_ctx; #define RDP_COMPR_BLK_LEN 8192 * 4 #pragma pack(push,1) typedef struct _RDP_pack_blk { DWORD len; BYTE data[RDP_COMPR_BLK_LEN + 12]; } RDP_pack_blk; #pragma pack(pop) @@ -134,6 +109,7 @@ init_pack_ctx(RDP_pack_ctx *c) { c->RDPCompress_GetContextSize = (_RDPCompress_GetContextSize)GetProcAddress(rdpbase, "RDPCompress_GetContextSize"); c->RDPCompress_InitSendContext = (_RDPCompress_InitSendContext)GetProcAddress(rdpbase, "RDPCompress_InitSendContext"); c->RDPCompress = (_RDPCompress)GetProcAddress(rdpbase, "RDPCompress"); c->RDPCompressEx = (_RDPCompressEx)GetProcAddress(rdpbase, "RDPCompressEx"); c->RDPDeCompress_GetContextSize = (_RDPDeCompress_GetContextSize)GetProcAddress(rdpbase, "RDPDeCompress_GetContextSize"); c->RDPCompress_InitRecvContext = (_RDPCompress_InitRecvContext)GetProcAddress(rdpbase, "RDPCompress_InitRecvContext"); @@ -142,6 +118,7 @@ init_pack_ctx(RDP_pack_ctx *c) { return c->RDPCompress_GetContextSize != NULL && c->RDPCompress_InitSendContext != NULL && c->RDPCompress != NULL && c->RDPCompressEx != NULL && c->RDPDeCompress_GetContextSize != NULL && c->RDPCompress_InitRecvContext != NULL && c->RDPDecompress != NULL; @@ -165,10 +142,10 @@ WriteFileData(std::string path, std::vector<BYTE> data) { // // Use RDP algorithms to compress file. // BOOL rdp_encode(RDP_pack_ctx *c) { void *SendCtx = NULL; BOOL result = false; do { DWORD ctx_len = c->RDPCompress_GetContextSize(c->type); @@ -181,35 +158,31 @@ rdp_encode(RDP_pack_ctx *c) { PBYTE inbuf = (PBYTE)c->inbuf.data(); DWORD inlen = c->inbuf.size(); DWORD cnt = 0; while (inlen) { RDP_pack_blk in={0}, out={0}; // 12 bytes are needed for header/flags in.len = inlen > c->blk - 12 ? c->blk - 12: inlen; out.len = c->blk; memcpy(in.data, inbuf, in.len); result = c->RDPCompressEx(c->type, in.data, in.len, out.data, &out.len, SendCtx); if (!result) { printf("RDPCompressEx failed for block %ld, %ld\n", cnt, in.len); break; } //printf("Block : %ld (%ld -> %ld) bytes...\n", cnt, in.len, out.len); c->outbuf.insert(c->outbuf.end(), (PBYTE)&out, (PBYTE)&out + out.len + sizeof(DWORD)); inlen -= in.len; inbuf += in.len; cnt++; } } while (false); if (SendCtx) free(SendCtx); @@ -219,10 +192,10 @@ rdp_encode(RDP_pack_ctx *c) { // // // BOOL rdp_decode(RDP_pack_ctx *c) { void *RecvContext = NULL; BOOL result = TRUE; do { DWORD ctx_len = c->RDPDeCompress_GetContextSize(c->type); @@ -233,31 +206,45 @@ rdp_decode(RDP_pack_ctx *c) { PBYTE inbuf = (PBYTE)c->inbuf.data(); DWORD inlen = c->inbuf.size(); DWORD cnt = 0; while (inlen) { RDP_pack_blk *in = (RDP_pack_blk*)inbuf; PBYTE outbuf = NULL; DWORD outlen = 0; result = c->RDPDecompress( in->data, in->len, 0, (PVOID*)&outbuf, &outlen, RecvContext, c->type); if (!result) { result = c->RDPDecompress( in->data, in->len, 1, (PVOID*)&outbuf, &outlen, RecvContext, c->type); if (!result) { printf("RDPDecompress() failed for block %ld, %ld -> %ld\n", cnt, in->len, outlen); break; } } //printf("Saving %ld bytes for block %ld...\n", outlen, cnt); c->outbuf.insert(c->outbuf.end(), outbuf, outbuf + outlen); inlen -= in->len + sizeof(DWORD); inbuf += in->len + sizeof(DWORD); cnt++; } } while (false); @@ -268,11 +255,19 @@ rdp_decode(RDP_pack_ctx *c) { int main(int argc, char *argv[]) { if ((argc != 4) || ((argv[1][0] != 'e') && (argv[1][0] != 'd'))) { printf("\nusage: rdp_pack [e/d]x <infile> <outfile>\n\n"); printf(" x denotes algorithm:\n\n"); printf(" 0 - MPPC-8K\n"); printf(" 1 - MPPC-64K\n"); printf(" 2 - NCRUSH\n"); printf(" 3 - XCRUSH\n\n"); printf("example compressing infile.txt with XCRUSH: rdp_pack e3 infile.txt outfile.bin\n"); return 0; } bool result, encode = (argv[1][0] == 'e'); int alg = argv[1][1] - '0'; const char* infile = argv[2]; const char* outfile = argv[3]; @@ -283,18 +278,54 @@ main(int argc, char *argv[]) { return 0; } switch(alg) { case 0: c.type = PACKET_COMPR_TYPE_8K; c.name = "MPPC-8K"; c.blk = 4096; break; case 1: c.type = PACKET_COMPR_TYPE_64K; c.name = "MPPC-64K"; c.blk = 8192; break; case 2: c.type = PACKET_COMPR_TYPE_RDP6; c.name = "NCRUSH"; c.blk = 8192; break; case 3: c.type = PACKET_COMPR_TYPE_RDP61; c.name = "XCRUSH"; c.blk = 8192; break; default: printf("Invalid compression algorithm specified.\n"); return 0; } c.inbuf = ReadFileData(infile); if (encode) { printf("Compressing %zd bytes in %s with %s\n", c.inbuf.size(), infile, c.name ); result = rdp_encode(&c); } else { printf("Decompressing %zd bytes in %s with %s\n", c.inbuf.size(), infile, c.name ); result = rdp_decode(&c); } if (result) { printf("Saving %zd bytes to %s.\n", c.outbuf.size(), outfile); WriteFileData(outfile, c.outbuf); } printf("Status : %s\n", result ? "OK" : "FAILED"); return 0; } -
odzhan revised this gist
Dec 31, 2023 . 1 changed file with 3 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -17,7 +17,8 @@ for the others. cl /EHsc rdp_pack.cpp compress: rdp_pack e infile outfile.8k decompress: rdp_pack d infile.8k outfile */ #include <windows.h> @@ -197,9 +198,7 @@ rdp_encode(RDP_pack_ctx *c) { } // no compression? if (out.len == RDP_COMPR_BLK_LEN) { // copy uncompressed memcpy(&out, &in, sizeof(RDP_pack_blk)); -
odzhan revised this gist
Dec 31, 2023 . 1 changed file with 4 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -16,6 +16,8 @@ The parameters to decompress data may be wrong. It appears to work fine for MPPC, but perhaps it won't work correctly for the others. cl /EHsc rdp_pack.cpp */ #include <windows.h> @@ -195,8 +197,8 @@ rdp_encode(RDP_pack_ctx *c) { } // no compression? if (c->type == PACKET_COMPR_TYPE_8K || c->type == PACKET_COMPR_TYPE_64K || out.len == RDP_COMPR_BLK_LEN) { // copy uncompressed -
odzhan renamed this gist
Dec 31, 2023 . 1 changed file with 22 additions and 12 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,20 @@ /** Compression using undocumented API in rdpbase.dll RDPCompress supports four algorithms : MPPC-8K, MPPC-64K, NCRUSH and XCRUSH. This code only supports compression and decompression using MPPC algorithms because these were the easiest to figure out. The MPPC compression ratio is very similar to LZSS, so this could be quite useful for shellcode trying to evade detection. I was unable to get decompression working for NCRUSH and XCRUSH, which is why I'm publishing this. Maybe someone will figure out how to provide the correct input for these. Internally, NCRUSH expects the length of uncompressed or compressed data in the buffer. If you discover correct input for NCRUSH or XCRUSH, please let me know. The parameters to decompress data may be wrong. It appears to work fine for MPPC, but perhaps it won't work correctly for the others. */ @@ -24,7 +34,7 @@ #pragma pack(push, 1) typedef struct { uint8_t header; // An 8-bit, unsigned integer specifying the compression type and flags uint8_t data[1]; // A variable-length array of bytes containing data encoded using RDP 8.0 Bulk Compression techniques } RDP8_BULK_ENCODED_DATA; #pragma pack(pop) @@ -51,7 +61,7 @@ typedef struct { #define PACKET_COMPR_TYPE_64K 1 // MPPC #define PACKET_COMPR_TYPE_RDP6 2 // NCRUSH #define PACKET_COMPR_TYPE_RDP61 3 // XCRUSH #define PACKET_COMPR_TYPE_RDP8 4 // MSDN references this, but I doubt it's actually supported by OS #define PACKET_ENCRYPTED 0x10 #define PACKET_COMPRESSED 0x20 @@ -153,7 +163,7 @@ WriteFileData(std::string path, std::vector<BYTE> data) { // Use RDP algorithms to compress file. // bool rdp_encode(RDP_pack_ctx *c) { void *SendCtx = NULL; bool result = false; @@ -185,12 +195,14 @@ rdp_pack(RDP_pack_ctx *c) { } // no compression? if (c.type == PACKET_COMPR_TYPE_8K || c.type == PACKET_COMPR_TYPE_64K || out.len == RDP_COMPR_BLK_LEN) { // copy uncompressed memcpy(&out, &in, sizeof(RDP_pack_blk)); } c->outbuf.insert(c->outbuf.end(), (PBYTE)&out, (PBYTE)&out + out.len + sizeof(DWORD)); inlen -= in.len; @@ -207,7 +219,7 @@ rdp_pack(RDP_pack_ctx *c) { // // bool rdp_decode(RDP_pack_ctx *c) { void *RecvContext = NULL; bool result = false; @@ -240,8 +252,6 @@ rdp_depack(RDP_pack_ctx *c) { } } c->outbuf.insert(c->outbuf.end(), outbuf, outbuf + outlen); start = 1; @@ -277,9 +287,9 @@ main(int argc, char *argv[]) { c.inbuf = ReadFileData(infile); if (encode) { rdp_encode(&c); } else { rdp_decode(&c); } // save output to file -
odzhan created this gist
Dec 31, 2023 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,289 @@ /** Compression using rdpbase.dll exports RDPCompress supports four algorithms : MPPC-8K, MPPC-64K, NCRUSH and XCRUSH. This code only supports compression and decompression using MPPC algorithms. */ #include <windows.h> #include <cstdio> #include <cstdint> #include <cstdlib> #include <cstring> #include <string> #include <vector> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #pragma pack(push, 1) typedef struct { uint8_t header; // An 8-bit, unsigned integer specifying the compression type and flags uint8_t data[1]; // A variable-length array of bytes containing data encoded using RDP 8.0 Bulk Compression techniques } RDP8_BULK_ENCODED_DATA; #pragma pack(pop) typedef struct { uint8_t descriptor; // SINGLE (0xE0) or MULTIPART (0xE1) // Optional fields uint16_t segmentCount; // Only present if descriptor is MULTIPART uint32_t uncompressedSize; // Only present if descriptor is MULTIPART RDP8_BULK_ENCODED_DATA bulkData; // Only present if descriptor is SINGLE //RDP_DATA_SEGMENT *segmentArray; // Only present if descriptor is MULTIPART } RDP_SEGMENTED_DATA_MP; #pragma pack(push, 1) typedef struct { uint32_t uncompressedSize; // Only present if descriptor is MULTIPART RDP8_BULK_ENCODED_DATA bulkData; // Only present if descriptor is SINGLE } RDP_SEGMENTED_DATA; #pragma pack(pop) // type of compression #define PACKET_COMPR_TYPE_8K 0 // MPPC #define PACKET_COMPR_TYPE_64K 1 // MPPC #define PACKET_COMPR_TYPE_RDP6 2 // NCRUSH #define PACKET_COMPR_TYPE_RDP61 3 // XCRUSH #define PACKET_COMPR_TYPE_RDP8 4 #define PACKET_ENCRYPTED 0x10 #define PACKET_COMPRESSED 0x20 #define PACKET_AT_FRONT 0x40 #define PACKET_FLUSHED 0x80 // ****************************************************** // Needed to allocate memory for compression context. typedef DWORD (WINAPI *_RDPCompress_GetContextSize)(DWORD ComprType); // Initialise compression context. typedef void (WINAPI *_RDPCompress_InitSendContext)(void *ctx, SIZE_T ctx_len, DWORD ComprType); // Compress inbuf and store in outbuf typedef DWORD (WINAPI *_RDPCompress)(DWORD ComprType, void *inbuf, void *outbuf, PDWORD outlen, void *ctx); // ****************************************************** typedef DWORD (WINAPI *_RDPDeCompress_GetContextSize)(DWORD ComprType); typedef void (WINAPI *_RDPCompress_InitRecvContext)(void *ctx, SIZE_T ctx_len, DWORD ComprType, void *workspace); typedef DWORD (WINAPI *_RDPDecompress)( PVOID inbuf, DWORD inlen, DWORD start, PVOID* outbuf, PDWORD outlen, PVOID RecvContext, DWORD ComprType ); typedef struct _RDP_pack_ctx { DWORD type; // compression algorithm _RDPCompress_GetContextSize RDPCompress_GetContextSize; _RDPCompress_InitSendContext RDPCompress_InitSendContext; _RDPCompress RDPCompress; _RDPDeCompress_GetContextSize RDPDeCompress_GetContextSize; _RDPCompress_InitRecvContext RDPCompress_InitRecvContext; _RDPDecompress RDPDecompress; std::vector<BYTE> inbuf, outbuf; } RDP_pack_ctx; #define RDP_COMPR_BLK_LEN 4096 #pragma pack(push,1) typedef struct _RDP_pack_blk { DWORD len; BYTE data[RDP_COMPR_BLK_LEN]; } RDP_pack_blk; #pragma pack(pop) bool init_pack_ctx(RDP_pack_ctx *c) { HMODULE rdpbase = LoadLibrary("rdpbase.dll"); if (!rdpbase) return false; c->RDPCompress_GetContextSize = (_RDPCompress_GetContextSize)GetProcAddress(rdpbase, "RDPCompress_GetContextSize"); c->RDPCompress_InitSendContext = (_RDPCompress_InitSendContext)GetProcAddress(rdpbase, "RDPCompress_InitSendContext"); c->RDPCompress = (_RDPCompress)GetProcAddress(rdpbase, "RDPCompress"); c->RDPDeCompress_GetContextSize = (_RDPDeCompress_GetContextSize)GetProcAddress(rdpbase, "RDPDeCompress_GetContextSize"); c->RDPCompress_InitRecvContext = (_RDPCompress_InitRecvContext)GetProcAddress(rdpbase, "RDPCompress_InitRecvContext"); c->RDPDecompress = (_RDPDecompress)GetProcAddress(rdpbase, "RDPDecompress"); return c->RDPCompress_GetContextSize != NULL && c->RDPCompress_InitSendContext != NULL && c->RDPCompress != NULL && c->RDPDeCompress_GetContextSize != NULL && c->RDPCompress_InitRecvContext != NULL && c->RDPDecompress != NULL; } std::vector<BYTE> ReadFileData(std::string path) { std::ifstream instream(path, std::ios::in | std::ios::binary); std::vector<BYTE> data((std::istreambuf_iterator<char>(instream)), std::istreambuf_iterator<char>()); return data; } bool WriteFileData(std::string path, std::vector<BYTE> data) { std::ofstream outstream(path, std::ios::out | std::ios::binary); if (!outstream) return false; std::copy(data.begin(), data.end(), std::ostreambuf_iterator<char>(outstream)); return outstream.good(); } // // Use RDP algorithms to compress file. // bool rdp_pack(RDP_pack_ctx *c) { void *SendCtx = NULL; bool result = false; do { DWORD ctx_len = c->RDPCompress_GetContextSize(c->type); if (!ctx_len) break; SendCtx = malloc(ctx_len); if (!SendCtx) break; c->RDPCompress_InitSendContext(SendCtx, ctx_len, c->type); PBYTE inbuf = (PBYTE)c->inbuf.data(); DWORD inlen = c->inbuf.size(); while (inlen) { RDP_pack_blk in={0}, out={0}; in.len = inlen > RDP_COMPR_BLK_LEN ? RDP_COMPR_BLK_LEN : inlen; out.len = in.len; memcpy(in.data, inbuf, in.len); c->RDPCompress(c->type, in.data, out.data, &out.len, SendCtx); if (!out.len) { printf("RDPCompress failed.\n"); break; } // no compression? if (out.len == RDP_COMPR_BLK_LEN) { // copy uncompressed memcpy(&out, &in, sizeof(RDP_pack_blk)); } //printf("Compressed %ld -> %ld...\n", in.len, out.len); c->outbuf.insert(c->outbuf.end(), (PBYTE)&out, (PBYTE)&out + out.len + sizeof(DWORD)); inlen -= in.len; inbuf += in.len; } result = true; } while (false); if (SendCtx) free(SendCtx); return result; } // // // bool rdp_depack(RDP_pack_ctx *c) { void *RecvContext = NULL; bool result = false; do { DWORD ctx_len = c->RDPDeCompress_GetContextSize(c->type); RecvContext = malloc(ctx_len); if (!RecvContext) break; c->RDPCompress_InitRecvContext(RecvContext, ctx_len, c->type, NULL); PBYTE inbuf = (PBYTE)c->inbuf.data(); DWORD inlen = c->inbuf.size(); DWORD start = 0; while (inlen) { RDP_pack_blk *in = (RDP_pack_blk*)inbuf; PBYTE outbuf = NULL; DWORD outlen = 0; if (in->len == RDP_COMPR_BLK_LEN) { outbuf = in->data; outlen = RDP_COMPR_BLK_LEN; } else { c->RDPDecompress(in->data, in->len, start, (PVOID*)&outbuf, &outlen, RecvContext, c->type); if (!outbuf) { printf("RDPDecompress() failed.\n"); break; } } //if (!outlen) break; //printf("Decompressed %ld -> %ld...\n", in->len, outlen); c->outbuf.insert(c->outbuf.end(), outbuf, outbuf + outlen); start = 1; inlen -= in->len + sizeof(DWORD); inbuf += in->len + sizeof(DWORD); } } while (false); if (RecvContext) free(RecvContext); return result; } int main(int argc, char *argv[]) { if ((argc != 4) || ((argv[1][0] != 'e') && (argv[1][0] != 'd'))) { printf("usage: rdp_pack [e/d] <infile> <outfile>\n"); return 0; } bool encode = (argv[1][0] == 'e'); const char* infile = argv[2]; const char* outfile = argv[3]; RDP_pack_ctx c; if (!init_pack_ctx(&c)) { printf("Unable to initialise RDP API.\n"); return 0; } // set compression and input data c.type = PACKET_COMPR_TYPE_8K; c.inbuf = ReadFileData(infile); if (encode) { rdp_pack(&c); } else { rdp_depack(&c); } // save output to file WriteFileData(outfile, c.outbuf); printf("OK\n"); return 0; }