USD Wiper with DoD 5220.22-M 04-27-2019, 08:26 PM
#1
I needed a USB wiper and I coded one really fast, if someone is needs one, here is the code. Its not perfect but makes the job right
EDIT: If you want to use it for hard drives comment out "if (DeviceInfo.Descriptor.RemovableMedia) {" from QueryAllRemovableDevices, also link with brypt.lib and the speed depends from your USB version/hard disk
Another edit: it requires admin privileges, otherwise will not find any drives
Code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <windows.h>
#include <winioctl.h>
#include <ntstatus.h>
#define SIZE_OF_GB (SIZE_OF_MB * 1024)
#define SIZE_OF_MB (SIZE_OF_KB * 1024)
#define SIZE_OF_KB (1 * 1024)
typedef double DOUBLE, *PDOUBLE;
typedef long double LDOUBLE, *PLDOUBLE;
typedef struct _DEVICE {
HANDLE Handle;
PWSTR szProductId;
ULONG dwBytesPerSector;
ULONG64 qwNumberOfSectors;
} DEVICE, *PDEVICE;
static DEVICE DeviceList[16];
static ULONG dwDevicesCount = 0;
static
BOOL
QueryAllRemovableDevices(VOID)
{
typedef union {
BYTE Buffer[MAX_PATH + sizeof(STORAGE_DEVICE_DESCRIPTOR)];
STORAGE_DEVICE_DESCRIPTOR Descriptor;
} DEVICE_QUERY_INFO, *PDEVICE_QUERY_INFO;
ULONG dwReturnedSize;
WCHAR szPhysicalDrive[20];
DEVICE_QUERY_INFO DeviceInfo;
DISK_GEOMETRY DeviceGeometry;
STORAGE_PROPERTY_QUERY DeviceQuery = {
StorageDeviceProperty,
PropertyStandardQuery,
0
};
for (ULONG_PTR i = 0; i != 15; i++) {
_snwprintf((PVOID)szPhysicalDrive, 20, L"\\??\\PhysicalDrive%lu", i);
HANDLE hDevice = CreateFileW(szPhysicalDrive, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hDevice) {
break;
}
if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &DeviceQuery, sizeof(DeviceQuery), &DeviceInfo, sizeof(DeviceInfo), &dwReturnedSize, NULL)) {
if (DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DeviceGeometry, sizeof(DeviceGeometry), &dwReturnedSize, NULL)) {
if (DeviceInfo.Descriptor.RemovableMedia) {
if (DeviceInfo.Descriptor.ProductIdOffset) {
PSTR szProdcutId = DeviceInfo.Buffer + DeviceInfo.Descriptor.ProductIdOffset;
SIZE_T cbProductId = strlen(szProdcutId);
DeviceList[dwDevicesCount].szProductId = malloc((cbProductId + 1) * 2);
MultiByteToWideChar(CP_OEMCP, 0, szProdcutId, cbProductId + 1, DeviceList[dwDevicesCount].szProductId, cbProductId + 1);
} else {
DeviceList[dwDevicesCount].szProductId = L"Null";
}
DeviceList[dwDevicesCount].Handle = hDevice;
DeviceList[dwDevicesCount].dwBytesPerSector = DeviceGeometry.BytesPerSector;
DeviceList[dwDevicesCount].qwNumberOfSectors = DeviceGeometry.SectorsPerTrack * DeviceGeometry.TracksPerCylinder * (ULONGLONG)DeviceGeometry.Cylinders.QuadPart;
dwDevicesCount++;
continue;
}
}
}
CloseHandle(hDevice);
}
return dwDevicesCount ? TRUE : FALSE;
}
static
PWSTR
ConvertSizeToUnits(
IN ULONG64 qwSize,
OUT PLDOUBLE ldSize
)
{
if (qwSize >= SIZE_OF_GB) {
*ldSize = (LDOUBLE)qwSize / (LDOUBLE)SIZE_OF_GB;
return L"GB";
} else if (qwSize >= SIZE_OF_MB) {
*ldSize = (LDOUBLE)qwSize / (LDOUBLE)SIZE_OF_MB;
return L"MB";
} else if (qwSize >= SIZE_OF_KB) {
*ldSize = (LDOUBLE)qwSize / (LDOUBLE)SIZE_OF_KB;
return L"KB";
} else {
*ldSize = (LDOUBLE)qwSize;
return L"B";
}
}
static BOOL bUpdateCounter = FALSE;
static
DWORD
WINAPI
OneMinuteTimer(VOID)
{
while (TRUE) {
Sleep(1000 * 60);
bUpdateCounter = TRUE;
}
}
int
wmain()
{
_setmode(_fileno(stdout), _O_U16TEXT);
if (!QueryAllRemovableDevices()) {
wprintf(L"Didn't find any USB drives\n");
getchar();
return -1;
}
ULONG dwUserChoice;
wprintf(L"\n ID │ Name │ Size\n"
L"────┼──────────────────────────────────┼──────────\n"
);
for (ULONG_PTR i = 0; i != dwDevicesCount; i++) {
LDOUBLE ldSize;
PWSTR szUnit = ConvertSizeToUnits(DeviceList[i].dwBytesPerSector * DeviceList[i].qwNumberOfSectors, &ldSize);
wprintf(L" % 2lu │ %-32ls │ %-6.2lf %ls\n", i, DeviceList[i].szProductId, ldSize, szUnit);
}
putwchar(L'\n');
while (TRUE) {
wprintf(L"Choice disk (0 - %lu): ", dwDevicesCount - 1);
scanf("%ld", &dwUserChoice);
if (dwUserChoice < dwDevicesCount) {
break;
}
}
for (ULONG_PTR i = 0; i != dwDevicesCount; i++) {
if (i == dwUserChoice) {
continue;
}
CloseHandle(DeviceList[i].Handle);
}
ULONG dwWritten;
HANDLE hDisk = DeviceList[dwUserChoice].Handle;
SIZE_T cbSector = DeviceList[dwUserChoice].dwBytesPerSector;
ULONG64 qwNumberOfSectors = DeviceList[dwUserChoice].qwNumberOfSectors;
PBYTE Sector = malloc(cbSector);
CreateThread(NULL, 0, (PVOID)&OneMinuteTimer, NULL, 0, NULL);
wprintf(L"\nIt might take several hours\n");
wprintf(L"Phase 1: Writting 0's\n");
memset(Sector, 0, cbSector);
bUpdateCounter = TRUE;
for (ULONG64 i = 0; i != qwNumberOfSectors; i++) {
if (bUpdateCounter) {
LDOUBLE ldDonePercent = (LDOUBLE)i / (LDOUBLE)qwNumberOfSectors;
ULONG_PTR dwCharIndex = 0;
ULONG_PTR dwCharsDone = ldDonePercent * 39.0;
wprintf(L"\r[");
while (dwCharIndex++ != dwCharsDone) {
putwchar(L'■');
}
while (dwCharIndex++ != 39) {
putwchar(L' ');
}
wprintf(L"] %3.0lf/100", ldDonePercent * 100.0);
bUpdateCounter = FALSE;
}
if (!WriteFile(hDisk, Sector, cbSector, &dwWritten, NULL)) {
CloseHandle(hDisk);
wprintf(L"Problem with writting\n");
getchar();
return -2;
}
}
wprintf(L"\r[■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■] 100/100\n");
wprintf(L"Phase 2: Writting binary 1's\n");
memset(Sector, 0xFF, cbSector);
bUpdateCounter = TRUE;
for (ULONG64 i = 0; i != qwNumberOfSectors; i++) {
if (bUpdateCounter) {
LDOUBLE ldDonePercent = (LDOUBLE)i / (LDOUBLE)qwNumberOfSectors;
ULONG_PTR dwCharIndex = 0;
ULONG_PTR dwCharsDone = ldDonePercent * 39.0;
wprintf(L"\r[");
while (dwCharIndex++ != dwCharsDone) {
putwchar(L'■');
}
while (dwCharIndex++ != 39) {
putwchar(L' ');
}
wprintf(L"] %3.0lf/100", ldDonePercent * 100.0);
bUpdateCounter = FALSE;
}
if (!WriteFile(hDisk, Sector, cbSector, &dwWritten, NULL)) {
CloseHandle(hDisk);
wprintf(L"Problem with writting\n");
getchar();
return -2;
}
}
wprintf(L"\r[■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■] 100/100\n");
wprintf(L"Phase 3: Writting random data\n");
bUpdateCounter = TRUE;
for (ULONG64 i = 0; i != qwNumberOfSectors; i++) {
if (bUpdateCounter) {
LDOUBLE ldDonePercent = (LDOUBLE)i / (LDOUBLE)qwNumberOfSectors;
ULONG_PTR dwCharIndex = 0;
ULONG_PTR dwCharsDone = ldDonePercent * 39.0;
wprintf(L"\r[");
while (dwCharIndex++ != dwCharsDone) {
putwchar(L'■');
}
while (dwCharIndex++ != 39) {
putwchar(L' ');
}
wprintf(L"] %3.0lf/100", ldDonePercent * 100.0);
bUpdateCounter = FALSE;
}
if (STATUS_SUCCESS != BCryptGenRandom(NULL, Sector, cbSector, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) {
CloseHandle(hDisk);
wprintf(L"Problem with random generator\n");
getchar();
return -3;
}
if (!WriteFile(hDisk, Sector, cbSector, &dwWritten, NULL)) {
CloseHandle(hDisk);
wprintf(L"Problem with writting\n");
getchar();
return -4;
}
}
wprintf(L"\r[■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■] 100/100\n");
CloseHandle(hDisk);
return 0;
}
EDIT: If you want to use it for hard drives comment out "if (DeviceInfo.Descriptor.RemovableMedia) {" from QueryAllRemovableDevices, also link with brypt.lib and the speed depends from your USB version/hard disk
Another edit: it requires admin privileges, otherwise will not find any drives
(This post was last modified: 04-29-2019, 05:24 AM by IsBadWritePtr.)