mirror of https://github.com/a0rtega/pafish
First commit of Curious Fish.
This commit is contained in:
parent
887cdd4877
commit
4dd1e14c1a
|
@ -0,0 +1,36 @@
|
|||
|
||||
CC = i686-w64-mingw32-gcc
|
||||
LINK = i686-w64-mingw32-gcc
|
||||
WINDRES = i686-w64-mingw32-windres
|
||||
OBJ = Objects/MingW/main.o Objects/MingW/common.o Objects/MingW/wmi.o \
|
||||
Objects/MingW/fingerprint.o Objects/MingW/cufish_private.res
|
||||
LINKOBJ = $(OBJ)
|
||||
LIBS = -lole32 -lwbemuuid -loleaut32 -lws2_32 -s
|
||||
INCS =
|
||||
BIN = Output/MingW/cufish.exe
|
||||
CFLAGS = $(INCS) -Wall -Wextra -O0
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
clean:
|
||||
rm -f Objects/MingW/*.o
|
||||
rm -f Objects/MingW/*.res
|
||||
rm -f Output/MingW/*.exe
|
||||
|
||||
$(BIN): $(OBJ)
|
||||
$(LINK) $(LINKOBJ) -o "$(BIN)" $(LIBS)
|
||||
|
||||
Objects/MingW/main.o: $(GLOBALDEPS) main.c
|
||||
$(CC) -c main.c -o Objects/MingW/main.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/common.o: $(GLOBALDEPS) common.c
|
||||
$(CC) -c common.c -o Objects/MingW/common.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/wmi.o: $(GLOBALDEPS) wmi.c
|
||||
$(CC) -c wmi.c -o Objects/MingW/wmi.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/fingerprint.o: $(GLOBALDEPS) fingerprint.c
|
||||
$(CC) -c fingerprint.c -o Objects/MingW/fingerprint.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/cufish_private.res: Objects/MingW/cufish_private.rc
|
||||
$(WINDRES) Objects/MingW/cufish_private.rc --input-format=rc -o Objects/MingW/cufish_private.res -O coff
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
CC = gcc.exe
|
||||
LINK = gcc.exe
|
||||
WINDRES = windres.exe
|
||||
OBJ = Objects/MingW/main.o Objects/MingW/common.o Objects/MingW/wmi.o \
|
||||
Objects/MingW/fingerprint.o Objects/MingW/cufish_private.res
|
||||
LINKOBJ = $(OBJ)
|
||||
LIBS = -lole32 -lwbemuuid -loleaut32 -lws2_32 -s
|
||||
INCS =
|
||||
BIN = Output/MingW/cufish.exe
|
||||
CFLAGS = $(INCS) -Wall -Wextra -O0
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
clean:
|
||||
del /Q Objects\MingW\*.o
|
||||
del /Q Objects\MingW\*.res
|
||||
del /Q Output\MingW\*.exe
|
||||
|
||||
$(BIN): $(OBJ)
|
||||
$(LINK) $(LINKOBJ) -o "$(BIN)" $(LIBS)
|
||||
|
||||
Objects/MingW/main.o: $(GLOBALDEPS) main.c
|
||||
$(CC) -c main.c -o Objects/MingW/main.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/common.o: $(GLOBALDEPS) common.c
|
||||
$(CC) -c common.c -o Objects/MingW/common.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/wmi.o: $(GLOBALDEPS) wmi.c
|
||||
$(CC) -c wmi.c -o Objects/MingW/wmi.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/fingerprint.o: $(GLOBALDEPS) fingerprint.c
|
||||
$(CC) -c fingerprint.c -o Objects/MingW/fingerprint.o $(CFLAGS)
|
||||
|
||||
Objects/MingW/cufish_private.res: Objects/MingW/cufish_private.rc
|
||||
$(WINDRES) Objects/MingW/cufish_private.rc --input-format=rc -o Objects/MingW/cufish_private.res -O coff
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
#include <windows.h>
|
||||
|
||||
A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "cufish.ico"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 0,5,2,1
|
||||
PRODUCTVERSION 0,5,2,1
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", ""
|
||||
VALUE "FileVersion", ""
|
||||
VALUE "FileDescription", "Curious Fish is curious"
|
||||
VALUE "InternalName", ""
|
||||
VALUE "LegalCopyright", ""
|
||||
VALUE "LegalTrademarks", ""
|
||||
VALUE "OriginalFilename", ""
|
||||
VALUE "ProductName", "Curious Fish"
|
||||
VALUE "ProductVersion", ""
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1252
|
||||
END
|
||||
END
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* The server address to send the logs to.
|
||||
*/
|
||||
static const char *server_addr = "192.168.1.1";
|
||||
/**
|
||||
* The server port.
|
||||
*/
|
||||
static const int server_port = 9876;
|
||||
/**
|
||||
* Socket to be used to send the logs from.
|
||||
*/
|
||||
SOCKET client_socket = INVALID_SOCKET;
|
||||
/**
|
||||
* Socket address to send the logs to.
|
||||
*/
|
||||
struct sockaddr_in socket_addr;
|
||||
|
||||
unsigned short init_cmd_colors() {
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
HANDLE handler = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// Get original console colors
|
||||
GetConsoleScreenBufferInfo(handler, &csbi);
|
||||
SetConsoleTextAttribute(handler, FOREGROUND_INTENSITY);
|
||||
// Return original console colors
|
||||
return csbi.wAttributes;
|
||||
}
|
||||
|
||||
void restore_cmd_colors(unsigned short original_colors) {
|
||||
HANDLE handler = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// Restore original console colors
|
||||
SetConsoleTextAttribute(handler, original_colors);
|
||||
}
|
||||
|
||||
void print_header() {
|
||||
HANDLE handler = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
printf("* Cufish (");
|
||||
SetConsoleTextAttribute(handler, 10);
|
||||
printf("Curious fish");
|
||||
SetConsoleTextAttribute(handler, FOREGROUND_INTENSITY);
|
||||
printf(") *\n\n");
|
||||
printf("Fingerprinting malware execution\n");
|
||||
printf("environments.\n\n");
|
||||
}
|
||||
|
||||
void print_ok() {
|
||||
HANDLE handler = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(handler, 10);
|
||||
printf("OK\n");
|
||||
SetConsoleTextAttribute(handler, FOREGROUND_INTENSITY);
|
||||
}
|
||||
|
||||
void print_failed() {
|
||||
HANDLE handler = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(handler, 207);
|
||||
printf("failed!\n");
|
||||
SetConsoleTextAttribute(handler, FOREGROUND_INTENSITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the log messane into a file.
|
||||
*/
|
||||
void write_log(wchar_t *message) {
|
||||
FILE *log = fopen("cufish.log", "a");
|
||||
fwprintf(log, L"\n[cufish] %s", message);
|
||||
fclose(log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the log message over the UDP socket. This function will convert the
|
||||
* message from a wide character string to a multiple byte string making it
|
||||
* easier to read when inspecting the network packet captures.
|
||||
*/
|
||||
void send_log(wchar_t *message) {
|
||||
size_t length = wcslen(message) + 2;
|
||||
|
||||
// Get a nice zero filled string.
|
||||
char *final = malloc(length * sizeof(char));
|
||||
memset(final, 0, length * sizeof(char));
|
||||
|
||||
wcstombs(final, message, length);
|
||||
strcat(final, "\n");
|
||||
|
||||
sendto(client_socket, final, strlen(final) * sizeof(char), 0,
|
||||
(SOCKADDR *) &socket_addr, sizeof(struct sockaddr_in));
|
||||
|
||||
free(final);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the UDP socket. Return TRUE if everything works out, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
int init_socket() {
|
||||
WSADATA wsaData;
|
||||
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
|
||||
WSACleanup();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
socket_addr.sin_family = AF_INET;
|
||||
socket_addr.sin_port = htons(server_port);
|
||||
socket_addr.sin_addr.s_addr = inet_addr(server_addr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the UDP socket.
|
||||
*/
|
||||
void clean_socket() {
|
||||
if (client_socket == INVALID_SOCKET) {
|
||||
closesocket(client_socket);
|
||||
}
|
||||
|
||||
WSACleanup();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
#ifndef COMM_H
|
||||
#define COMM_H
|
||||
|
||||
unsigned short init_cmd_colors();
|
||||
|
||||
void restore_cmd_colors(unsigned short);
|
||||
|
||||
void print_header();
|
||||
|
||||
void print_failed();
|
||||
|
||||
void print_ok();
|
||||
|
||||
int init_socket();
|
||||
|
||||
void write_log(wchar_t *);
|
||||
|
||||
void send_log(wchar_t *);
|
||||
|
||||
int init_socket();
|
||||
|
||||
void clean_socket();
|
||||
|
||||
#endif
|
Binary file not shown.
After Width: | Height: | Size: 347 KiB |
|
@ -0,0 +1,279 @@
|
|||
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
#include <wbemidl.h>
|
||||
|
||||
#include "wmi.h"
|
||||
#include "fingerprint.h"
|
||||
|
||||
struct wmitarget wmitargets[] = {
|
||||
{
|
||||
L"Operating System", L"Win32_OperatingSystem", {
|
||||
L"Caption", L"Description", L"InstallDate", L"Name", L"CountryCode",
|
||||
L"FreePhysicalMemory", L"FreeVirtualMemory", L"MaxProcessMemorySize",
|
||||
L"Version", L"LastBootUpTime", L"TotalSwapSpaceSize",
|
||||
L"TotalVirtualMemorySize", L"TotalVisibleMemorySize", L"BootDevice",
|
||||
L"BuildNumber", L"BuildType", L"CodeSet", L"CountryCode",
|
||||
L"DataExecutionPrevention_Available", L"DataExecutionPrevention_32BitApplications",
|
||||
L"DataExecutionPrevention_Drivers", L"DataExecutionPrevention_SupportPolicy",
|
||||
L"Debug", L"Locale", L"Manufacturer", L"Organization", L"OSLanguage",
|
||||
L"OSProductSuite", L"PlusProductID", L"PlusVersionNumber",
|
||||
L"RegisteredUser", L"SerialNumber", L"ServicePackMajorVersion",
|
||||
L"ServicePackMinorVersion", L"SystemDevice", L"SystemDirectory", L"SystemDrive",
|
||||
L"WindowsDirectory", L"PAEEnabled",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Computer System", L"Win32_ComputerSystem", {
|
||||
L"Caption", L"Description", L"Name", L"PrimaryOwnerContact",
|
||||
L"PrimaryOwnerName", L"DNSHostName", L"Domain", L"Manufacturer", L"Model",
|
||||
L"SystemType", L"UserName", L"OEMStringArray", L"TotalPhysicalMemory",
|
||||
L"Workgroup",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Page File", L"Win32_PageFileUsage", {
|
||||
L"Caption", L"Description", L"Name", L"AllocatedBaseSize", L"CurrentUsage",
|
||||
L"PeakUsage", L"TempPageFile",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Processor", L"Win32_Processor", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"AddressWidth",
|
||||
L"DataWidth", L"Family", L"OtherFamilyDescription", L"MaxClockSpeed", L"Stepping",
|
||||
L"UniqueId", L"Version", L"Manufacturer", L"L2CacheSize", L"L2CacheSpeed",
|
||||
L"L3CacheSize", L"L3CacheSpeed", L"Architecture", L"Level", L"Revision",
|
||||
L"ProcessorId", L"ProcessorType", L"NumberOfLogicalProcessors", L"NumberOfCores",
|
||||
L"SocketDesignation",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"BIOS", L"Win32_BIOS", {
|
||||
L"Caption", L"Description", L"Name", L"Version", L"SoftwareElementState",
|
||||
L"SoftwareElementID", L"Manufacturer", L"BuildNumber", L"SerialNumber", L"CodeSet",
|
||||
L"IdentificationCode", L"LanguageEdition", L"ReleaseDate", L"SMBIOSPresent",
|
||||
L"SMBIOSMajorVersion", L"SMBIOSMinorVersion", L"SMBIOSBIOSVersion",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Device", L"Win32_PnPEntity", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"HardwareID",
|
||||
L"CompatibleID", L"Manufacturer", L"Service", L"ClassGuid",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"CD-ROM", L"Win32_CDROMDrive", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"MaxMediaSize",
|
||||
L"DefaultBlockSize", L"MaxBlockSize", L"MinBlockSize", L"NumberOfMediaSupported",
|
||||
L"Manufacturer", L"MediaType", L"RevisionLevel", L"VolumeName", L"VolumeSerialNumber",
|
||||
L"MediaLoaded", L"Size", L"SerialNumber", L"Drive",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Sound Device", L"Win32_SoundDevice", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Manufacturer",
|
||||
L"ProductName",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Video Controller", L"Win32_VideoController", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"TimeOfLastReset",
|
||||
L"VideoProcessor", L"VideoMemoryType", L"NumberOfVideoPages", L"MaxMemorySupported",
|
||||
L"CurrentBitsPerPixel", L"CurrentHorizontalResolution", L"CurrentVerticalResolution",
|
||||
L"MaxRefreshRate", L"MinRefreshRate", L"CurrentRefreshRate", L"CurrentNumberOfColors",
|
||||
L"VideoMode", L"AdapterCompatibility", L"AdapterDACType", L"AdapterRAM", L"InfSection",
|
||||
L"InstalledDisplayDrivers", L"DriverDate", L"DriverVersion", L"SpecificationVersion",
|
||||
L"VideoModeDescription",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Keyboard", L"Win32_Keyboard", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Layout",
|
||||
L"NumberOfFunctionKeys",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Pointing Device", L"Win32_PointingDevice", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Handedness",
|
||||
L"NumberOfButtons", L"PointingType", L"Resolution", L"HardwareType", L"InfSection",
|
||||
L"SampleRate", L"Manufacturer",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Network Adapter", L"Win32_NetworkAdapter", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"PermanentAddress",
|
||||
L"NetworkAddresses", L"Speed", L"MaxSpeed", L"ProductName", L"AdapterType",
|
||||
L"MACAddress", L"ServiceName", L"Manufacturer", L"NetConnectionID", L"GUID",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Network Adapter Configuration", L"Win32_NetworkAdapterConfiguration", {
|
||||
L"SettingID", L"Caption", L"Description", L"DefaultIPGateway", L"DHCPLeaseExpires",
|
||||
L"DHCPLeaseObtained", L"DHCPServer", L"IPAddress", L"IPSubnet", L"MACAddress", L"ServiceName",
|
||||
L"DatabasePath", L"DNSHostName", L"DNSDomain", L"DNSServerSearchOrder",
|
||||
L"DNSDomainSuffixSearchOrder", L"WINSPrimaryServer", L"WINSSecondaryServer", L"WINSHostLookupFile",
|
||||
L"WINSScopeID",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Serial Ports", L"Win32_SerialPort", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"CapabilityDescriptions",
|
||||
L"ProviderType",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Parallel Ports", L"Win32_ParallelPort", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"CapabilityDescriptions",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Logical Disks", L"Win32_LogicalDisk", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"ErrorMethodology",
|
||||
L"Purpose", L"Compressed", L"DriveType", L"FileSystem", L"ProviderName", L"VolumeName",
|
||||
L"VolumeSerialNumber", L"MediaType",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Disk Partition", L"Win32_DiskPartition", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"ErrorMethodology",
|
||||
L"Purpose", L"BootPartition", L"Type",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"SCSI Controller", L"Win32_SCSIController", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"DriverName", L"DeviceMap",
|
||||
L"HardwareVersion", L"Manufacturer",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"IDE Controller", L"Win32_IDEController", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Manufacturer",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"USB Controller", L"Win32_USBController", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Manufacturer",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Drivers", L"Win32_SystemDriver", {
|
||||
L"Caption", L"Description", L"Name", L"StartMode", L"Started", L"DisplayName", L"PathName",
|
||||
L"ServiceType", L"StartName", L"State",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Services", L"Win32_Service", {
|
||||
L"Caption", L"Description", L"Name", L"StartMode", L"Started", L"DisplayName", L"PathName",
|
||||
L"ServiceType", L"StartName", L"State", L"ProcessId",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Environment Variables", L"Win32_Environment", {
|
||||
L"Caption", L"Description", L"Name", L"SystemVariable", L"UserName", L"VariableValue",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Network Connections", L"Win32_NetworkConnection", {
|
||||
L"Caption", L"Description", L"Name", L"Comment", L"ConnectionType", L"ConnectionState", L"DisplayType",
|
||||
L"LocalName", L"ProviderName", L"RemoteName", L"RemotePath", L"ResourceType", L"UserName",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Processes", L"Win32_Process", {
|
||||
L"Caption", L"Description", L"Name", L"CreationDate", L"Handle", L"Priority", L"ExecutionState",
|
||||
L"TerminationDate", L"ExecutablePath", L"ProcessId", L"ParentProcessId", L"SessionId", L"CommandLine",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Program Groups", L"Win32_LogicalProgramGroup", {
|
||||
L"Caption", L"Description", L"Name", L"GroupName", L"UserName",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Startup Command", L"Win32_StartupCommand", {
|
||||
L"SettingID", L"Caption", L"Description", L"User", L"Name", L"Location", L"Command",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Accounts", L"Win32_Account", {
|
||||
L"Caption", L"Description", L"Name", L"Domain", L"SID", L"SIDType", L"LocalAccount",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Base Board", L"Win32_BaseBoard", {
|
||||
L"Caption", L"Description", L"Name", L"Manufacturer", L"Model", L"SKU", L"SerialNumber",
|
||||
L"Tag", L"Version", L"PartNumber", L"HostingBoard", L"SlotLayout", L"Product",
|
||||
L"ConfigOptions",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Desktop Monitor", L"Win32_DesktopMonitor", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"MonitorManufacturer",
|
||||
L"ScreenHeight", L"ScreenWidth", L"MonitorType",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Disk Drives", L"Win32_DiskDrive", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Manufacturer",
|
||||
L"MediaLoaded", L"MediaType", L"Model", L"SerialNumber", L"FirmwareRevision",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Floppy Controller", L"Win32_FloppyController", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Manufacturer",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Mapped Logical Disks", L"Win32_MappedLogicalDisk", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"Purpose", L"SessionID",
|
||||
L"FileSystem", L"VolumeName", L"VolumeSerialNumber", L"ProviderName",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Motherboard Device", L"Win32_MotherboardDevice", {
|
||||
L"Caption", L"Description", L"Name", L"DeviceID", L"PNPDeviceID", L"PrimaryBusType", L"RevisionNumber",
|
||||
L"SecondaryBusType",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{
|
||||
L"Software Features", L"Win32_SoftwareFeature", {
|
||||
L"Caption", L"Description", L"Name", L"IdentifyingNumber", L"ProductName", L"Vendor", L"Version",
|
||||
NULL
|
||||
}
|
||||
},
|
||||
{ NULL, NULL, { NULL } }
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
#ifndef FINGERPRINT_H
|
||||
#define FINGERPRINT_H
|
||||
|
||||
extern struct wmitarget wmitargets[];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <wbemidl.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "common.h"
|
||||
#include "wmi.h"
|
||||
#include "fingerprint.h"
|
||||
|
||||
/*
|
||||
Cufish (Curious fish)
|
||||
|
||||
All code from this project, including
|
||||
functions, procedures and the main program
|
||||
is licensed under GNU/GPL version 3.
|
||||
|
||||
So, if you are going to use functions or
|
||||
procedures from this project to develop
|
||||
your malware, you have to release the
|
||||
source code as well :)
|
||||
|
||||
- Alberto Ortega
|
||||
- Duarte Silva
|
||||
|
||||
Green fish icon thanks to http://www.fasticon.com/
|
||||
|
||||
*/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned short original_colors = 0;
|
||||
IWbemServices *services = NULL;
|
||||
int index = 0;
|
||||
|
||||
write_log(L"Start");
|
||||
|
||||
original_colors = init_cmd_colors();
|
||||
print_header();
|
||||
|
||||
printf("[*] Initializing socket ... ");
|
||||
if (init_socket() != TRUE) {
|
||||
print_failed();
|
||||
}
|
||||
else {
|
||||
print_ok();
|
||||
|
||||
printf("\n[-] Obtaining data using WMI\n");
|
||||
printf("[*] Starting WMI client ... ");
|
||||
if (wmi_initialize(&services) != TRUE) {
|
||||
print_failed();
|
||||
}
|
||||
else {
|
||||
print_ok();
|
||||
|
||||
for (index = 0; wmitargets[index].caption != NULL; index++) {
|
||||
wprintf(L"[*] Obtaining %s data ... ", wmitargets[index].caption);
|
||||
if (wmi_execute_query(services, wmitargets[index].caption, wmitargets[index].classname,
|
||||
wmitargets[index].properties) != TRUE) {
|
||||
print_failed();
|
||||
}
|
||||
else print_ok();
|
||||
}
|
||||
|
||||
printf("[*] Cleanup WMI client ... \n");
|
||||
wmi_cleanup(services);
|
||||
}
|
||||
|
||||
printf("\n[*] Cleanup socket ...\n");
|
||||
clean_socket();
|
||||
}
|
||||
|
||||
printf("\n\n");
|
||||
printf("[-] Feel free to RE me, check log file for more information.");
|
||||
|
||||
write_log(L"End");
|
||||
|
||||
getchar();
|
||||
|
||||
/* Restore Original Console Colors */
|
||||
restore_cmd_colors(original_colors);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#endif
|
|
@ -0,0 +1,315 @@
|
|||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
#include <wbemidl.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "common.h"
|
||||
#include "wmi.h"
|
||||
|
||||
/**
|
||||
* WMI namespace where queries will be executed.
|
||||
*/
|
||||
static const wchar_t *query_namespace = L"root\\cimv2";
|
||||
/**
|
||||
* WMI query format.
|
||||
*/
|
||||
static const wchar_t *query_format = L"SELECT %s FROM %s";
|
||||
/**
|
||||
* WMI query properties separator.
|
||||
*/
|
||||
static const wchar_t *query_separator = L",";
|
||||
/**
|
||||
* WMI query language.
|
||||
*/
|
||||
static const wchar_t *query_language = L"WQL";
|
||||
|
||||
/**
|
||||
* Construct a WMI query with the provided class name and properties. The query
|
||||
* will be returned as a BSTR. The calling code is responsible for freeing the
|
||||
* allocated memory for it.
|
||||
*/
|
||||
BSTR construct_query(wchar_t *class_name, wchar_t *properties[]) {
|
||||
wchar_t *expression;
|
||||
wchar_t *query;
|
||||
size_t count;
|
||||
size_t length;
|
||||
BSTR result;
|
||||
|
||||
// Count the number of properties and calculate the combined length of
|
||||
// them all.
|
||||
for (count = 0, length = 0; properties[count] != NULL; count++) {
|
||||
length = length + wcslen(properties[count]);
|
||||
}
|
||||
|
||||
// Account for the comma separators (should be "count - 1" but since
|
||||
// the string needs to be null terminated, it allocates that extra
|
||||
// character).
|
||||
length = length + count;
|
||||
|
||||
// Get a nice zero filled string.
|
||||
expression = (wchar_t *) malloc(length * sizeof(wchar_t));
|
||||
memset(expression, 0, length * sizeof(wchar_t));
|
||||
|
||||
for (count = 0; properties[count] != NULL; count++) {
|
||||
wcscat(expression, properties[count]);
|
||||
|
||||
// If there is a next element, add the comma separator.
|
||||
if (properties[count + 1] != NULL) {
|
||||
wcscat(expression, query_separator);
|
||||
}
|
||||
}
|
||||
|
||||
// The length for the query is calculated based on the expression, the
|
||||
// class name, and the query format. The extra character for string
|
||||
// termination isn't necessary since the query format will give extra
|
||||
// characters (4 in total).
|
||||
length = wcslen(expression) + wcslen(class_name) + wcslen(query_format);
|
||||
|
||||
query = (wchar_t *) malloc(length * sizeof(wchar_t));
|
||||
memset(query, 0, length * sizeof(wchar_t));
|
||||
|
||||
snwprintf(query, length, query_format, expression, class_name);
|
||||
|
||||
result = SysAllocString(query);
|
||||
|
||||
// Free allocated memory.
|
||||
free(expression);
|
||||
free(query);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report to the application log and the UDP socket. Maximum size for each line
|
||||
* is 2048 wide characters (4096 bytes).
|
||||
*/
|
||||
void wmi_report(wchar_t *format, ...) {
|
||||
wchar_t formated[2048] = { 0 };
|
||||
va_list arglist;
|
||||
|
||||
va_start(arglist, format);
|
||||
vswprintf(formated, 2048, format, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
write_log(formated);
|
||||
send_log(formated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a VARIANT that is an array. Note that this function only supports
|
||||
* VARIANT's that are strings.
|
||||
*/
|
||||
void wmi_handle_array(wchar_t *property, VARIANT *value) {
|
||||
wchar_t *element;
|
||||
long index, count, upper_bound = 0, lower_bound = 0;
|
||||
|
||||
SAFEARRAY *safe_array = V_ARRAY(value);
|
||||
|
||||
SafeArrayGetUBound(safe_array, 1, &upper_bound);
|
||||
SafeArrayGetLBound(safe_array, 1, &lower_bound);
|
||||
|
||||
count = upper_bound - lower_bound + 1;
|
||||
wmi_report(L"- %s:", property);
|
||||
|
||||
for (index = 0; index < count; ++index) {
|
||||
SafeArrayGetElement(safe_array, &index, &element);
|
||||
|
||||
wmi_report(L" - %s", element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function responsible for extracting from the instance the property value and
|
||||
* reporting it. Note that 64 bits CIM properties in a 32 bits application (at
|
||||
* least) are encoded as strings, so V_BSTR is used instead of V_UI8.
|
||||
*/
|
||||
void wmi_handle_property(IWbemClassObject *instance, wchar_t *property) {
|
||||
CIMTYPE type = CIM_ILLEGAL;
|
||||
VARIANT value;
|
||||
|
||||
HRESULT hresult = instance->lpVtbl->Get(instance, property, 0, &value, &type, 0);
|
||||
|
||||
if (FAILED(hresult) || V_VT(&value) == VT_NULL) {
|
||||
wmi_report(L"- %s: Null", property);
|
||||
}
|
||||
else {
|
||||
switch (type) {
|
||||
case CIM_ILLEGAL:
|
||||
wmi_report(L"- %s: Illegal", property);
|
||||
break;
|
||||
case CIM_EMPTY:
|
||||
wmi_report(L"- %s: Empty", property);
|
||||
break;
|
||||
case CIM_SINT8:
|
||||
wmi_report(L"- %s: %i", property, V_I1(&value));
|
||||
break;
|
||||
case CIM_UINT8:
|
||||
wmi_report(L"- %s: %u", property, V_UI1(&value));
|
||||
break;
|
||||
case CIM_SINT16:
|
||||
wmi_report(L"- %s: %i", property, V_I2(&value));
|
||||
break;
|
||||
case CIM_UINT16:
|
||||
wmi_report(L"- %s: %u", property, V_UI2(&value));
|
||||
break;
|
||||
case CIM_SINT32:
|
||||
wmi_report(L"- %s: %i", property, V_I4(&value));
|
||||
break;
|
||||
case CIM_UINT32:
|
||||
wmi_report(L"- %s: %u", property, V_UI4(&value));
|
||||
break;
|
||||
case CIM_SINT64:
|
||||
wmi_report(L"- %s: %s", property, V_BSTR(&value));
|
||||
break;
|
||||
case CIM_UINT64:
|
||||
wmi_report(L"- %s: %s", property, V_BSTR(&value));
|
||||
break;
|
||||
case CIM_BOOLEAN:
|
||||
wmi_report(L"- %s: %s", property, V_BOOL(&value) ? L"True" : L"False");
|
||||
break;
|
||||
case CIM_STRING:
|
||||
wmi_report(L"- %s: %s", property, V_BSTR(&value));
|
||||
break;
|
||||
case CIM_DATETIME:
|
||||
wmi_report(L"- %s: %s", property, V_BSTR(&value));
|
||||
break;
|
||||
case CIM_CHAR16:
|
||||
wmi_report(L"- %s: %i", property, V_I2(&value));
|
||||
break;
|
||||
case CIM_STRING|CIM_FLAG_ARRAY:
|
||||
wmi_handle_array(property, &value);
|
||||
break;
|
||||
default:
|
||||
wmi_report(L"- %s: Unsupported", property);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a WMI class instance and report the selected properties value.
|
||||
*/
|
||||
void wmi_handle_instance(IWbemClassObject *instance, wchar_t *properties[]) {
|
||||
ULONG index;
|
||||
VARIANT value;
|
||||
|
||||
for (index = 0; properties[index] != NULL; index++) {
|
||||
wmi_handle_property(instance, properties[index]);
|
||||
}
|
||||
|
||||
VariantClear(&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the WMI query based on the class name and the selected properties,
|
||||
* execute the query and report for each instance its properties values.
|
||||
*/
|
||||
int wmi_execute_query(IWbemServices *services, wchar_t *caption, wchar_t *classname,
|
||||
wchar_t *properties[]) {
|
||||
int status = TRUE;
|
||||
IEnumWbemClassObject *queryrows = NULL;
|
||||
IWbemClassObject *batchrows[10];
|
||||
BSTR language = SysAllocString(query_language);
|
||||
BSTR wmiquery;
|
||||
|
||||
wmiquery = construct_query(classname, properties);
|
||||
|
||||
// Execute the query.
|
||||
HRESULT result = services->lpVtbl->ExecQuery(
|
||||
services, language, wmiquery, WBEM_FLAG_BIDIRECTIONAL, NULL, &queryrows);
|
||||
|
||||
if (!FAILED(result) && (queryrows != NULL)) {
|
||||
ULONG index, count = 0;
|
||||
result = WBEM_S_NO_ERROR;
|
||||
|
||||
while (WBEM_S_NO_ERROR == result) {
|
||||
// Retrieve 10 rows (instances) each time.
|
||||
result = queryrows->lpVtbl->Next(queryrows, WBEM_INFINITE, 10,
|
||||
batchrows, &count);
|
||||
|
||||
if (!SUCCEEDED(result)) {
|
||||
continue;
|
||||
}
|
||||
// For each instance returned, report the properties
|
||||
// values.
|
||||
for (index = 0; index < count; index++) {
|
||||
wmi_report(L"Start %s", caption);
|
||||
wmi_handle_instance(batchrows[index], properties);
|
||||
wmi_report(L"End", caption);
|
||||
|
||||
batchrows[index]->lpVtbl->Release(batchrows[index]);
|
||||
}
|
||||
}
|
||||
|
||||
queryrows->lpVtbl->Release(queryrows);
|
||||
}
|
||||
else {
|
||||
status = FALSE;
|
||||
}
|
||||
|
||||
SysFreeString(wmiquery);
|
||||
SysFreeString(language);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the WMI client that will connect to the local machine WMI
|
||||
* namespace. It will return TRUE if the connection was successful, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
int wmi_initialize(IWbemServices **services) {
|
||||
BSTR namespace;
|
||||
IWbemLocator *locator = NULL;
|
||||
int result;
|
||||
|
||||
HRESULT hresult = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
|
||||
if (FAILED(hresult)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hresult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
|
||||
|
||||
if (FAILED(hresult)) {
|
||||
CoUninitialize();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hresult = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
|
||||
&IID_IWbemLocator, (LPVOID *) &locator);
|
||||
|
||||
if (FAILED(hresult)) {
|
||||
CoUninitialize();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
namespace = SysAllocString(query_namespace);
|
||||
|
||||
// Connect to the namespace with the current user and obtain pointer
|
||||
// services to make IWbemServices calls.
|
||||
hresult = locator->lpVtbl->ConnectServer(locator, namespace, NULL, NULL, NULL, 0,
|
||||
NULL, NULL, services);
|
||||
|
||||
result = FAILED(hresult) ? FALSE : TRUE;
|
||||
|
||||
SysFreeString(namespace);
|
||||
locator->lpVtbl->Release(locator);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup WMI.
|
||||
*/
|
||||
void wmi_cleanup(IWbemServices *services) {
|
||||
if (services != NULL) {
|
||||
services->lpVtbl->Release(services);
|
||||
}
|
||||
|
||||
CoUninitialize();
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#ifndef WMI_H
|
||||
#define WMI_H
|
||||
|
||||
/**
|
||||
* Structure that contains the name of the class to query and the respective
|
||||
* properties. Note that the maximum number of properties is forty.
|
||||
*/
|
||||
struct wmitarget {
|
||||
wchar_t *caption;
|
||||
wchar_t *classname;
|
||||
wchar_t *properties[40];
|
||||
};
|
||||
|
||||
int wmi_initialize(IWbemServices **);
|
||||
|
||||
void wmi_cleanup(IWbemServices *);
|
||||
|
||||
int wmi_execute_query(IWbemServices *, wchar_t *, wchar_t *, wchar_t *[]);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue