PDA

View Full Version : hd spoofer from ring0


S@t@nic@
8th June 2006, 22:21
for hardware banned guys...


/*
simple ring0 hd serial spoofer by Orkblutt aka s@t@nic@
credits:
Taurine for his sample on NtDeviceIoControlFile
jiurl for port hidder method
Bruce Allen & smartmontools devs
*/

#include <ntddk.h>

#define IOCTL_STORAGE_BASE 0x0000002d
#define IOCTL_DISK_BASE 0x00000007

#define IOCTL_STORAGE_QUERY_PROPERTY \
CTL_CODE(IOCTL_STORAGE_BASE, 0x0500,METHOD_BUFFERED, FILE_ANY_ACCESS)

#define SMART_RCV_DRIVE_DATA \
CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define ATA_IDENTIFY_DEVICE 0xec

#pragma pack(1)

typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;

struct ata_identify_device {
unsigned short words000_009[10];
unsigned char serial_no[20];
unsigned short words020_022[3];
unsigned char fw_rev[8];
unsigned char model[40];
unsigned short words047_079[33];
unsigned short major_rev_num;
unsigned short minor_rev_num;
unsigned short command_set_1;
unsigned short command_set_2;
unsigned short command_set_extension;
unsigned short cfs_enable_1;
unsigned short word086;
unsigned short csf_default;
unsigned short words088_255[168];
};

typedef enum _STORAGE_BUS_TYPE {
BusTypeUnknown = 0x00,
BusTypeScsi,
BusTypeAtapi,
BusTypeAta,
BusType1394,
BusTypeSsa,
BusTypeFibre,
BusTypeUsb,
BusTypeRAID,
BusTypeMaxReserved = 0x7F
} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;

// retrieve the storage device descriptor data for a device.
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
ULONG Version;
ULONG Size;
UCHAR DeviceType;
UCHAR DeviceTypeModifier;
BOOLEAN RemovableMedia;
BOOLEAN CommandQueueing;
ULONG VendorIdOffset;
ULONG ProductIdOffset;
ULONG ProductRevisionOffset;
ULONG SerialNumberOffset;
STORAGE_BUS_TYPE BusType;
ULONG RawPropertiesLength;
UCHAR RawDeviceProperties[1];

} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;


#pragma pack()

#pragma pack(1)

typedef struct _GETVERSIONOUTPARAMS {
UCHAR bVersion;
UCHAR bRevision;
UCHAR bReserved;
UCHAR bIDEDeviceMap;
ULONG fCapabilities;
ULONG dwReserved[4];
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;


typedef struct _IDEREGS {
UCHAR bFeaturesReg;
UCHAR bSectorCountReg;
UCHAR bSectorNumberReg;
UCHAR bCylLowReg;
UCHAR bCylHighReg;
UCHAR bDriveHeadReg;
UCHAR bCommandReg;
UCHAR bReserved;
} IDEREGS, *PIDEREGS, *LPIDEREGS;

typedef struct _SENDCMDINPARAMS {
ULONG cBufferSize;
IDEREGS irDriveRegs;
UCHAR bDriveNumber;
UCHAR bReserved[3];
ULONG dwReserved[4];
UCHAR bBuffer[1];
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;


typedef struct _DRIVERSTATUS {
UCHAR bDriverError;
UCHAR bIDEError;
UCHAR bReserved[2];
ULONG dwReserved[2];
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;

typedef struct _SENDCMDOUTPARAMS {
ULONG cBufferSize;
DRIVERSTATUS DriverStatus;
UCHAR bBuffer[1];
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;


#pragma pack()


__declspec(dllimport) ServiceDescriptorTableEntry_t
KeServiceDescriptorTable;


// smartmontools code to deal with non big endian system

// Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
// bytes.
void swapbytes(char *out, const char *in, size_t n)
{
size_t i;

for (i = 0; i < n; i += 2) {
out[i] = in[i+1];
out[i+1] = in[i];
}
}

// Copies in to out, but removes leading and trailing whitespace.
void trim(char *out, const char *in)
{
int i, first, last;

// Find the first non-space character (maybe none).
first = -1;
for (i = 0; in[i]; i++)
if (!isspace((int)in[i])) {
first = i;
break;
}

if (first == -1) {
// There are no non-space characters.
out[0] = '\0';
return;
}

// Find the last non-space character.
for (i = strlen(in)-1; i >= first && isspace((int)in[i]); i--)
;
last = i;

strncpy(out, in+first, last-first+1);
out[last-first+1] = '\0';
}

// Convenience function for formatting strings from ata_identify_device
void formatdriveidstring(char *out, const char *in, int n)
{
char tmp[65];
n = n > 64 ? 64 : n;
swapbytes(tmp, in, n);
tmp[n] = '\0';
trim(out, tmp);
}



NTSYSAPI
NTSTATUS
NTAPI ZwDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);


typedef NTSTATUS (*ZWDEVICEIOCONTROLFILE)(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);


ZWDEVICEIOCONTROLFILE OldZwDeviceIoControlFile;

NTSTATUS NewZwDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength)
{

PSTORAGE_DEVICE_DESCRIPTOR output;
PSENDCMDINPARAMS cmdinput;
PSENDCMDOUTPARAMS cmdoutput;
struct ata_identify_device *hdid;

NTSTATUS rc;
rc = ((ZWDEVICEIOCONTROLFILE)(OldZwDeviceIoControlFile) ) (
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength
);



if(IoControlCode != IOCTL_STORAGE_QUERY_PROPERTY && IoControlCode != SMART_RCV_DRIVE_DATA)
return(rc);

if(NT_SUCCESS(rc))
{
switch( IoControlCode )
{
case IOCTL_STORAGE_QUERY_PROPERTY:

output = (PSTORAGE_DEVICE_DESCRIPTOR) OutputBuffer;
if( output->SerialNumberOffset )
{
char* serialnum = (char*)output + output->SerialNumberOffset;
formatdriveidstring(serialnum, "FAKE SERIAL", 40);
}

if( output->ProductIdOffset )
{
char* productid = (char*)output + output->ProductIdOffset;
strncpy( productid, "STUPID PB", strlen(productid) );
}

if( output->VendorIdOffset )
{
char* vendorid = (char*)output + output->VendorIdOffset;
strncpy( vendorid, "asdfghjkl", strlen(vendorid) );
}

break;

case SMART_RCV_DRIVE_DATA:

cmdinput = (PSENDCMDINPARAMS) InputBuffer;
cmdoutput = (PSENDCMDOUTPARAMS) OutputBuffer;

if (cmdinput->irDriveRegs.bCommandReg == ATA_IDENTIFY_DEVICE)
{
hdid = (struct ata_identify_device*) (cmdoutput->bBuffer);
formatdriveidstring(hdid->model, "spoofed model!", 40 );
formatdriveidstring( hdid->serial_no, "serial goes here", 20 );
}
break;
}
}

return(rc);

}


NTSTATUS DriverDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{

Irp->IoStatus.Status = STATUS_SUCCESS;

IoCompleteRequest (Irp,IO_NO_INCREMENT);

return Irp->IoStatus.Status;
}



void DriverUnload(IN PDRIVER_OBJECT DriverObject)
{

_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}

(KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)ZwDeviceIoControlFile+1)])
= (ULONG)OldZwDeviceIoControlFile;

_asm

{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{

DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverDispatch;

DriverObject->DriverUnload = DriverUnload;

// save old system call locations

OldZwDeviceIoControlFile = (ZWDEVICEIOCONTROLFILE)(KeServiceDescriptorTable.S erviceTableBase[
*(PULONG)((PUCHAR)ZwDeviceIoControlFile+1)]);

_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}

(KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)ZwDeviceIoControlFile+1)])
= (ULONG)NewZwDeviceIoControlFile;

_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}

return STATUS_SUCCESS;
}

Trundle
8th June 2006, 22:41
Nice method, but this won't work for v70 and v71 games (e.g. army or bf2), because you does not spoof the MACs and because PB does not call NtDeviceIoControlFile in their kernel driver ;)

S@t@nic@
8th June 2006, 22:51
hmmm... it's just an help for HW banned guys who want to code a anti HW ban framework...
i don't know what you need to change exactly to bypass pb... but i'm sure this code is working to spoof HD serial number, model and firmware version. anyway i'm sure it's also really easy to spoof MAC @...

where is the pb's kernel driver?i never try to deal with pb (just with ss cleaner atm) and i was believing pb was using only user mode detection system in AAO... can u give me more infos on that?

KizZamP-
8th June 2006, 22:51
this is way behind my knowledge,for sure...nice job :)

Trundle
8th June 2006, 23:02
hmmm... it's just an help for HW banned guys who want to code a anti HW ban framework...
i don't know what you need to change exactly to bypass pb... but i'm sure this code is working to spoof HD serial number, model and firmware version.

Only for usermode calls of DeviceIoControlFile ;)

where is the pb's kernel driver?i never try to deal with pb (just with ss cleaner atm) and i was believing pb was using only user mode detection system in AAO... can u give me more infos on that?
Yeah, I can. Well, everytime you join a server pb extracts a file to the tmp folder. This file contains the driver code. This driver is started via CreateServiceA, the checks are done (the driver itself does the whole IO on the devices again, hashes that results and sends that hash back to the usermode client), and then the driver is unloaded and the file is deleted...
if you need further infos, just add me to your msn!

Cya :)

PS: Sorry for my sucky English!

S@t@nic@
8th June 2006, 23:12
Only for usermode calls of DeviceIoControlFile

sure... :)


Yeah, I can. Well, everytime you join a server pb extracts a file to the tmp folder. This file contains the driver code. This driver is started via CreateServiceA, the checks are done (the driver itself does the whole IO on the devices again, hashes that results and sends that hash back to the usermode client), and then the driver is unloaded and the file is deleted...


really nice info here... i really didn't know about that... lol... thanks... :)

HUMM3R
9th June 2006, 08:24
for hardware banned guys...



A very similar code was published by taurine in january or so, but as Trundle said it wont work, not necessarily becaue of non-spoofed MAC (I wasted lot of time testing various spoofing before I read the article from GameDeception), but because one of the hashes used for HWID is generated from info get via direct I/O query. You can't spoof that. So if you get a fully prepared hash collection from a different machine and use that in your spoofer, you don't even need to get lower than user level. ;)
But in that case, if PB catches me, and bans my spoofed hardware, is it illegal? Because it banned hwid get from a computer that never saw AA, PB or anything like that. Maybe its a so old computer, that AA wont even run on it :)
God Save The Queen, I always liked punks ;)

Trundle
9th June 2006, 08:33
A very similar code was published by taurine in january or so, but as Trundle said it wont work, not necessarily becaue of non-spoofed MAC (I wasted lot of time testing various spoofing before I read the article from GameDeception), but because one of the hashes used for HWID is generated from info get via direct I/O query. You can't spoof that. So if you get a fully prepared hash collection from a different machine and use that in your spoofer, you don't even need to get lower than user level. ;)
That direct IO query hash (I havent wasted lots of time in that and so I may be wrong) only contains device and vendor IDs and so it is useless for detecting a HW banned machine...

S@t@nic@
9th June 2006, 21:09
A very similar code was published by taurine in january or so

http://forum.gamedeception.net/showpost.php?p=54346&postcount=81

yep.. from user level... exactly the same thing there but from kernel level.

anyway as u said guys, it's totally useless for hard banned guys...

HockeyBuster
9th June 2006, 22:50
I'm curious if anyone has tried spoofing o/s prvileges. While pb does the scan, fake your privileges to be admin, however once the scan is taken place return the real value which would fail the scan.

Of course, this would only take a easy patch to fix, however we all know punkbuster does not like adding extra precautions untill they are forced to.

S@t@nic@
9th June 2006, 22:55
let me understand? in what case o/s privileges can be usefull to change exactly?

SmokeyMcPott
11th June 2006, 22:24
I can't get this to work .I get about 20 compilling errors.
If someone want to send me the exe ,feel free to pm me.
thx

kizzamplover4vr
12th June 2006, 00:55
Firstly, this wont work for you like it is.... You dont have the skill to get it compiled and so i doubt you will be able to make it work. Dont waste your time on this and do something useful with your time ;) Learn C++ for example!

HUMM3R
12th June 2006, 11:48
http://forum.gamedeception.net/showpost.php?p=54346&postcount=81

yep.. from user level... exactly the same thing there but from kernel level.


Nope, check MPC, Anti-Cheat forum for it, link
http://www.mpcforum.com/showthread.php?t=117293

But anyway, it didn't work, it contained also mac spoofing, but nope. because:

That direct IO query hash (I havent wasted lots of time in that and so I may be wrong) only contains device and vendor IDs and so it is useless for detecting a HW banned machine...

Well, I was unfortunate and that ID is useful for banning my hw ass... It shouldn't be that way, but it is. I tested alot Taurines driver, spoofing my mac,hdd smart info, hdd serial, the driver was working ok, because if I returned error codes from functions, pb client reacted accordingly, and I've seen my mac also changed. So its not my hdd and not my nic card banned, and I dont have anything else bannable on my machine, so it must be the device infos. And yes, I tried lots of private spoofers and none worked of course.

let me understand? in what case o/s privileges can be usefull to change exactly?

I think no case, not having privileges will result in false info, or error, that is HW banned. The empty buffer for hash is always HW banned. Failure to retrieve HW info (error code) is also HW banned. I think the hash must be the correct version, and in correct format, verifiable for even be considered not HW banned. Thats what I noticed while testing my spoofer.

S@t@nic@
12th June 2006, 13:24
Nope, check MPC, Anti-Cheat forum for it, link
http://www.mpcforum.com/showthread.php?t=117293


ehehe... i need to look around before to post something :)
Gil could you move this thread in the anti AC forum please?

Trundle
13th June 2006, 08:38
Well, I was unfortunate and that ID is useful for banning my hw ass... It shouldn't be that way, but it is. I tested alot Taurines driver, spoofing my mac,hdd smart info, hdd serial, the driver was working ok, because if I returned error codes from functions, pb client reacted accordingly, and I've seen my mac also changed. So its not my hdd and not my nic card banned, and I dont have anything else bannable on my machine, so it must be the device infos. And yes, I tried lots of private spoofers and none worked of course.
You know that PB uses also other Usermode API's to check the MAC/serials?!

HUMM3R
13th June 2006, 10:30
You know that PB uses also other Usermode API's to check the MAC/serials?!

No, I didn't know that. And those usermode API functions are : ??
But I think that in the end the ZwDeviceIoControlFile gets called, and thats what the driver hooked. Changing some registry values had no effect on anything on my system, so I say its a myth that PB is using the MAC stored in registry.
But I'm 100% sure its not my nic banned and not my second HDD, because those were unplugged. Also not my tv tuner. So it has to be the 'i' hash. But I'm just to lazy to try if it is so, it would take only 1 day of my life ;)

gil
15th June 2006, 22:05
Gil could you move this thread in the anti AC forum please?

Moved :)

S@t@nic@
16th June 2006, 19:22
back... lol

2FACETANNER
18th June 2006, 20:36
Sorry for asking such a noobish question, where do you attack this code?

KizZamP-
18th June 2006, 21:05
1)double post.
2)lol ones attach,and once attack.
3)Microsoft Visual Studio .net 2003/2005/whatever.
4)i know you play AAO,and it doesn't work for that game anyways...