First commit of Curious Fish.

This commit is contained in:
Duarte Silva 2015-06-04 19:48:42 +01:00
parent 887cdd4877
commit 4dd1e14c1a
13 changed files with 972 additions and 0 deletions

36
cufish/Makefile.linux Normal file
View File

@ -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

36
cufish/Makefile.win Normal file
View File

@ -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

View File

@ -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
cufish/Output/MingW/.gitignore vendored Normal file
View File

129
cufish/common.c Normal file
View File

@ -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();
}

25
cufish/common.h Normal file
View File

@ -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

BIN
cufish/cufish.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

279
cufish/fingerprint.c Normal file
View File

@ -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 } }
};

7
cufish/fingerprint.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef FINGERPRINT_H
#define FINGERPRINT_H
extern struct wmitarget wmitargets[];
#endif

85
cufish/main.c Normal file
View File

@ -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;
}

8
cufish/types.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef TYPES_H
#define TYPES_H
#define TRUE 1
#define FALSE 0
#endif

315
cufish/wmi.c Normal file
View File

@ -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();
}

21
cufish/wmi.h Normal file
View File

@ -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