Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

768 lines
19 KiB

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntdddisk.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <io.h>
#define CB_LINE 16
#define SECSIZE 512
#define CB_INPUT 2
#define CB_INPUTLINE 8
#define CB_CMDLINE 256
typedef UCHAR BYTE,*PBYTE;
BYTE Sector[SECSIZE];
BYTE Input[CB_INPUT];
char Command[CB_CMDLINE];
UCHAR HexLine[80];
UCHAR CharLine[40];
BOOLEAN Batch = FALSE;
#define LoadWORD(x) ((ULONG)( (USHORT)(* (PBYTE)(x) ) \
| ((USHORT)(*((PBYTE)(x) + 1)) << 8) ))
#define LoadDWORD(x) ((LoadWORD((PBYTE)(x)+2) << 16) | LoadWORD(x))
typedef struct {
BYTE BootIndicator;
BYTE StartHead;
BYTE StartSector;
BYTE StartCylinder;
BYTE SysID;
BYTE EndHead;
BYTE EndSector;
BYTE EndCylinder;
BYTE Relative0;
BYTE Relative1;
BYTE Relative2;
BYTE Relative3;
BYTE SectorCount0;
BYTE SectorCount1;
BYTE SectorCount2;
BYTE SectorCount3;
} PTE,*PPTE;
#define PARTITIONTABLE_OFFSET 0x1be
#define SIGNATURE_OFFSET 0x1fe
typedef struct {
BYTE BootCode[PARTITIONTABLE_OFFSET];
PTE PartitionTable[4];
BYTE Signature[2];
} BOOTSECTOR,*PBOOTSECTOR;
BOOLEAN
IsSepChar(
int *Pc
)
{
switch (*Pc) {
case ',':
*Pc = ' ';
return TRUE;
case '\n':
*Pc = '\r';
return TRUE;
case ' ':
if( Batch )
return FALSE;
// else fall thru to '\r' case
case '\r':
return TRUE;
}
// if didn't return above, must not be separator
return FALSE;
}
int MyGetChr( void )
{
if (Batch) {
int c;
while ((c = getchar()) == ' ')
;
return c;
} else {
return _getch();
}
}
void PromptUsr( void )
{
if (!Batch)
printf("\n$ ");
}
BOOLEAN
OpenFile(
PSZ DriveNumber,
PHANDLE Handle
)
{
OBJECT_ATTRIBUTES oa;
STRING ntDriveName;
UNICODE_STRING uniDriveName;
IO_STATUS_BLOCK ioStatusBlock;
int charsInName;
char driveName[50];
NTSTATUS nts;
sprintf(driveName, "\\Device\\Harddisk%s\\Partition0", DriveNumber);
charsInName = strlen(driveName);
ntDriveName.Length = (USHORT)charsInName;
ntDriveName.MaximumLength = (USHORT)charsInName;
ntDriveName.Buffer = driveName;
printf( "NT drive name = %s\n", ntDriveName.Buffer );
RtlAnsiStringToUnicodeString(&uniDriveName, &ntDriveName, TRUE);
memset(&oa, 0, sizeof(OBJECT_ATTRIBUTES));
oa.Length = sizeof(OBJECT_ATTRIBUTES);
oa.ObjectName = &uniDriveName;
oa.Attributes = OBJ_CASE_INSENSITIVE;
if (!NT_SUCCESS(nts = NtOpenFile(Handle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&oa,
&ioStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT))) {
printf("NtOpenFile status %x\n", nts);
return FALSE;
}
RtlFreeUnicodeString(&uniDriveName);
return TRUE;
}
BOOLEAN
CloseFile(
HANDLE Handle
)
{
NTSTATUS nts;
if (!NT_SUCCESS(nts = NtClose(Handle))) {
printf("NtClose status %x\n");
return FALSE;
} else {
return TRUE;
}
}
BOOLEAN
LockVolume(
HANDLE Handle
)
{
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS nts;
if (!NT_SUCCESS(nts = NtFsControlFile(Handle,
NULL,
NULL,
NULL,
&ioStatusBlock,
FSCTL_LOCK_VOLUME,
NULL,
0,
NULL,
0))) {
printf("Unable to lock volume (%x).\n",
nts);
return FALSE;
} else {
return TRUE;
}
}
BOOLEAN
UnlockVolume(
HANDLE Handle
)
{
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS nts;
if (!NT_SUCCESS(nts = NtFsControlFile(Handle,
NULL,
NULL,
NULL,
&ioStatusBlock,
FSCTL_UNLOCK_VOLUME,
NULL,
0,
NULL,
0))) {
printf("Unable to unlock volume (%x).\n",
nts);
return FALSE;
} else {
return TRUE;
}
}
BOOLEAN
ReadSector(
HANDLE Handle,
ULONG Lsn,
PVOID Buffer,
PULONG BytesRead
)
{
IO_STATUS_BLOCK ioStatusBlock;
LARGE_INTEGER byteOffset;
NTSTATUS nts;
byteOffset.HighPart = 0;
byteOffset.LowPart = Lsn;
ioStatusBlock.Status = 0;
ioStatusBlock.Information = 0;
nts = NtReadFile(Handle,
0,
NULL,
NULL,
&ioStatusBlock,
Buffer,
SECSIZE,
&byteOffset,
NULL);
if(!NT_SUCCESS(nts)) {
printf("Read failed.\n");
printf(" Returned status: %lx\n", nts);
printf(" Final status: %lx\n", ioStatusBlock.Status);
return FALSE;
}
*BytesRead = ioStatusBlock.Information;
return TRUE;
}
BOOLEAN
WriteSector(
HANDLE Handle,
ULONG Offset,
PVOID Buffer
)
{
IO_STATUS_BLOCK ioStatusBlock;
LARGE_INTEGER byteOffset;
byteOffset.HighPart = 0;
byteOffset.LowPart = Offset;
if (!NT_SUCCESS(NtWriteFile(Handle,
NULL,
NULL,
NULL,
&ioStatusBlock,
Buffer,
SECSIZE,
&byteOffset,
NULL))) {
return FALSE;
}
return TRUE;
}
/*
* BOOLEAN MyGetInput( int *Pi, char *Pc )
*
* read hex input from line and convert into byte
*
* Returns TRUE if a number was entered
* FALSE if number should not be changed.
*
* *Pi == new number
* *Pc == terminating character (either ' ' or '\r')
*/
BOOLEAN
MyGetInput(
int *Pi,
char *Pc
)
{
int j,i = 0;
int c;
for(;;) {
c = MyGetChr();
c = toupper(c);
if (IsSepChar(&c)) {
// term char, exit loop
break;
} else if (c == '\b' && i != 0) {
// backspace over last char
printf("\b \b");
i--;
} else if (i < sizeof(Input) &&
(isdigit(c) || (c>= 'A' && c <= 'F'))) {
// good hex digit, store it
putchar(c);
if( isdigit(c) ) {
// convert digit to hex val
c -= '0';
} else {
// covert char to hex val
c = (c - 'A') + 10;
}
Input[i++] = (BYTE)c;
} else {
// some sort of error
//DosBeep( 1000, 250 );
}
}
*Pc = (char)c;
*Pi = 0;
for (j = 0; j < i; j++) {
*Pi = *Pi * 16 + Input[j];
}
return ((BOOLEAN)(i != 0));
}
void
_CRTAPI1 main(
int ArgC,
char *ArgS[]
)
{
HANDLE handle;
ULONG bytesRead;
ULONG lsn;
int i;
int j;
int lines;
char c;
char lastCmd;
char currentDrive[12];
PPTE partitionTable;
BOOLEAN modify = FALSE;
BOOLEAN more = FALSE;
// Disable hard-error popups.
SetErrorMode(TRUE);
// See if we are connected to CON
Batch = (BOOLEAN)(!isatty(0));
switch (ArgC) {
case 2:
// Nothing to do for level 2
break;
case 3:
if (strcmp(_strupr(ArgS[2]), "/E") == 0) {
modify = TRUE;
fprintf(stderr,
"Warning: Opening drive %s for write access!\n", ArgS[1]);
break;
} else {
fprintf(stderr, "%s: Invalid option '%s'\n", ArgS[0], ArgS[2]);
}
// Note fall through to default: (usage case)
default:
if (ArgC > 3)
fprintf(stderr, "%s: Too many arguments\n", ArgS[0]);
fprintf(stderr, "usage: %s diskno [/e]\n", ArgS[0]);
// Re-enable harderror popups.
SetErrorMode(FALSE);
exit(-1);
break;
}
sprintf(currentDrive, "%s", ArgS[1]);
if (!OpenFile(currentDrive, &handle)) {
fprintf(stderr,
"%s: Unable to open %s\n", ArgS[0], currentDrive);
// Re-enable harderror popups.
SetErrorMode(FALSE);
exit(1);
}
// check if we want to do writes with dasd
if (modify) {
// This is a drive, and we want to modify it, so we need
// to lock it.
if (!LockVolume(handle)) {
printf("Unable to lock volume.\n");
// Re-enable harderror popups.
SetErrorMode(FALSE);
exit(1);
}
}
// default to sector 0
lsn = 0;
while (1)
{
PromptUsr();
if (fgets(Command, sizeof(Command), stdin) == NULL)
break;
if ((i = sscanf(Command, "%c %li", &c, &lsn)) > 1) {
if ((c != 'c') && (c != 'C')) {
/*
* The user entered a lsn as well as an lsn based command,
* convert it to byte seek pos
*/
lsn *= SECSIZE;
}
}
more = FALSE;
c = (char)tolower((int)c);
// pre process command
if (c == 'q')
break;
if (c == '\n')
c = lastCmd;
switch (c) {
case 'b':
if (i == 1 && lastCmd == c) {
// same command with no new lsn, use the next one on disk
lsn -= bytesRead;
}
break;
case 'c':
// change drives.
if (i != 2) {
fprintf(stderr,
"You must specify a drive number to change drives.\n");
continue;
}
CloseFile(handle);
sprintf(currentDrive, "%d", lsn);
if (!OpenFile(currentDrive, &handle)) {
fprintf(stderr,
"%s: Unable to open %s\n", ArgS[0], currentDrive);
// Re-enable harderror popups.
SetErrorMode(FALSE);
exit(1);
}
// check if we want to do writes with dasd
if (modify) {
// This is a drive, and we want to modify it, so we need
// to lock it.
if (!LockVolume(handle)) {
printf("Unable to lock volume.\n");
// Re-enable harderror popups.
SetErrorMode(FALSE);
exit(1);
}
}
// default to sector 0
lsn = 0;
continue;
case 'g':
{
DISK_GEOMETRY diskGeometry;
IO_STATUS_BLOCK statusBlock;
NTSTATUS status;
// Get and display drive geometry from system.
status = NtDeviceIoControlFile(handle,
0,
NULL,
NULL,
&statusBlock,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY));
if (NT_SUCCESS(status)) {
printf("BytesPerSector: %d\n", diskGeometry.BytesPerSector);
printf("SectorsPerTrack: %d\n", diskGeometry.SectorsPerTrack);
printf("TracksPerCylinder: %d\n", diskGeometry.TracksPerCylinder);
printf("NumberOfCylinders: %d\n", diskGeometry.Cylinders);
} else {
fprintf(stderr, "Could not get geometry %x\n", status);
}
continue;
}
case 'm':
case 'd':
case 'e':
case 'p':
if (i == 1 && lastCmd == c) {
// same command with no new lsn, use the next one on disk
lsn += bytesRead;
}
break;
default:
fprintf(stderr,"Unknown command '%c'\n", c);
case 'h':
case '?':
fprintf(stderr," d [####]\tDump sector ####\n");
fprintf(stderr," e [####]\tEdit sector ####\n");
fprintf(stderr," m [####]\tDump sector with 'MORE'\n");
fprintf(stderr," b [####]\tSame as 'd' but defaults to"
" previous sector\n");
fprintf(stderr," c [##]\tChange harddisk number\n");
fprintf(stderr," p [####]\tDump partition table on sector ###\n");
fprintf(stderr," q \tquit the program");
fprintf(stderr,"\n"
"\n If no new sector is given and the command is the same, the next"
"\n sector on the disk is used. If no sector is given but the command"
"\n is different from the previous command, the sector used in the"
"\n last command will be used again.\n"
);
continue;
}
// remember last command
lastCmd = c;
bytesRead = 0;
if(!ReadSector(handle, lsn, Sector, &bytesRead)) {
printf("Unable to read sector %lx\n", lsn);
} else {
printf("\n lsn:0x%lX bytes read:%d\n", lsn / SECSIZE, bytesRead);
switch (c) {
case 'm':
/*
* More
*/
more = TRUE;
// fall through to Dump
case 'd':
case 'b':
/*
* Dump
*/
lines = 0;
HexLine[0] = '\0';
CharLine[0] = '\0';
i = 0;
sprintf(HexLine, "%04X ", i);
for (i = 0; i < (int)bytesRead; i++) {
sprintf(HexLine, "%s%2x ", HexLine, Sector[i]);
sprintf(CharLine, "%s%c", CharLine,
(isprint(Sector[i])) ? Sector[i] : '.');
if ((i != 0) && ((i % 16) == 15))
{
printf("%s *%s*\n", HexLine, CharLine);
HexLine[0] = '\0';
sprintf(HexLine, "%04X ", i + 1);
CharLine[0] = '\0';
lines++;
}
if (more && (lines == 20)) {
printf("\n--MORE--");
MyGetChr();
printf("\r");
lines = 0;
}
}
putchar('\n');
break;
case 'p':
/*
* dump partition table
*/
if (LoadWORD(&Sector[SIGNATURE_OFFSET]) == 0xaa55) {
partitionTable = ((PBOOTSECTOR)Sector)->PartitionTable;
for (i = 0; i < 4; i++) {
printf("\nEntry #%u:\n",i);
printf(" Boot flag : %u\n",
partitionTable[i].BootIndicator);
printf(" System ID : %u\n",
partitionTable[i].SysID);
printf(" Relative sectors: %u (0x%x)\n",
LoadDWORD(&partitionTable[i].Relative0),
LoadDWORD(&partitionTable[i].Relative0));
printf(" Sector count : %u (0x%x) [%u MB]\n",
LoadDWORD(&partitionTable[i].SectorCount0),
LoadDWORD(&partitionTable[i].SectorCount0),
(LoadDWORD(&partitionTable[i].SectorCount0) *
SECSIZE) / (1024*1024));
printf(" Start CHS : %u %u %u\n",
partitionTable[i].StartCylinder |
((partitionTable[i].StartSector & 0xc0) << 2),
partitionTable[i].StartHead,
partitionTable[i].StartSector & 0x3f);
printf(" End CHS : %u %u %u\n",
partitionTable[i].EndCylinder |
((partitionTable[i].EndSector & 0xc0) << 2),
partitionTable[i].EndHead,
partitionTable[i].EndSector & 0x3f);
}
} else {
printf("\nSector %u is not a valid master boot sector.\n",
lsn/SECSIZE);
}
break;
case 'e':
/*
* Edit
*/
if (!modify) {
printf("Can not edit, restart with /e option\n");
} else {
for (i = 0; i < (int)bytesRead; i++) {
if ((i % CB_INPUTLINE) == 0) {
// print line header
printf("\n%04X\t", i);
}
printf("%02X.", (BYTE)Sector[i]);
if (MyGetInput(&j, &c )) {
Sector[i] = (BYTE)j;
} else {
printf("%02X", (BYTE)Sector[i]);
}
if (c == '\r')
break;
putchar('\t');
}
printf("\nWrite new data to sector? (Y/N)");
c = (char)MyGetChr();
if ((c = (char)toupper(c)) == 'Y') {
// User wants to save the data
printf("Yes....");
if (!WriteSector(handle, lsn, Sector)) {
fprintf(stderr, "Write failed\n");
} else {
// indicate success
printf("\t[Done]\n");
}
} else {
// user chickened out
printf("No....\t[Nothing written]\n");
}
}
break;
}
}
}
// if this was a dasd open, then unlock the drive
if (modify) {
UnlockVolume(handle);
}
CloseFile(handle);
// Re-enable harderror popups.
SetErrorMode(FALSE);
exit(0);
}