Thread overview
Accessing > 64MB of RAM; using DOS 32-bit extender
Mar 30, 2007
Denzien
Apr 02, 2007
Kevin G. Rhoads
Apr 04, 2007
Heinz Saathoff
March 30, 2007
Hi everyone, I'm working on a simple application to research the true volatility of RAM in my Digital Forensics class and I've run into a small roadblock.

I've read that I can (possibly) address up to 3/4 of the available system memory using the x32 DOS extender, but my application can only malloc up to about 64MB.

The idea of the program is simple: after booting into a very small footprint OS (DOS), allocate all available memory and fill that memory with identifiable "needles".  After rebooting the machine, again run the application to re-allocate the memory and then search for the needles in memory (in lieu of performing a memory dump and using a hard drive).  This is designed to be run from a CD for fast results on a variety of machines (Laptop, Desktop, Workstation, different brand names, etc)

The file is named Needler.cpp, and I from its directory I compile
using the following command:
"c:\dm\bin\dmc Needler.cpp -Ae -ml -mx x32.lib"

The following is my simple and un-optimized code that seems to work great in the first 64MB:

/********************************/
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <malloc.h>
#include <x32.h>
#include <dos.h>

#define KB  1024
#define MB (1024 * KB)

void processArguments(int argc, char* argv[]);
void writeMenu();
void hideNeedles(char * buffer);
int FindNeedles();
int ByteToInt(char *data);
void PrintMenu();
char* doMalloc();
int SearchMemory(int offset);

void *_x386_zero_base_ptr;

int plantedNeedles = 0;
int needleLength = 53;
char needle[53]
= "ABCDEFGHIJKLMNOPQRSTUVWXYZzyxwvutsrqponmlkjihgfedcba";

bool verbose = false;
bool read = false;
bool write = false;

int main(int argc, char* argv[])
{
	int result;// = SearchMemory();
	processArguments(argc, argv);

	if (read || write)
	{
		printf("\nPerforming Operations...\n\n");
		result = FindNeedles();
	}
	else
	{
		writeMenu();
		return 0;
	}
	if (read) printf("\n\nFound %i needles in the haystack.",
result);
	return 0;
}

void processArguments(int argc, char* argv[])
{
	char verboseSwitch[3] = "-v";
	char readSwitch[3] = "-r";
	char writeSwitch[3] = "-w";
	for(int i = 0; i < argc; i++)
	{
		if(argv[i][1] == verboseSwitch[1]) verbose = true;
		else if(argv[i][1] == readSwitch[1]) read = true;
		else if(argv[i][1] == writeSwitch[1]) write = true;
		else if(argv[i][1] == 'o')
		{
			int x = ByteToInt(argv[++i]);
			printf("\nOffset = %i\n\n", x);
			//x = SearchMemory(x);
		}
	}
}

int ByteToInt(char *data)
{
	int result = 0;
	int i = 0;
	while(data[i] != 0)
	{
	/*for (int i = 0; i < 20; i++)
	{*/
		if(((int)data[i] >= 0x30) && ((int)data[i] <=
0x39))
		{
			result *= 10;

			switch(data[i])
			{
				case '1':
					result += 1;
					break;
				case '2':
					result += 2;
					break;
				case '3':
					result += 3;
					break;
				case '4':
					result += 4;
					break;
				case '5':
					result += 5;
					break;
				case '6':
					result += 6;
					break;
				case '7':
					result += 7;
					break;
				case '8':
					result += 8;
					break;
				case '9':
					result += 9;
					break;
				default:
					break;
			}
		}
		/*else if(data[i] == 0x0)
			return result;*/
		i++;
	}

	return result;
}

void writeMenu()
{
	printf("\n\nUsage:\n");
	printf("  -w  Write needles into memory\n");
	printf("  -r  Read needles from memory\n");
	printf("  -v  Verbose output (makes processing very slow)
\n   *Must also choose read or write.\n\n");
	printf(" If both read and write are specified,\n  Needler
will write needles first, then read.\n\n");
}

char* doMalloc()
{
	unsigned long Kilobyte = 1024;
	char * buffer = (char*) malloc (Kilobyte * 64);
	//if (buffer == NULL) buffer = (char*) malloc (KB);
	if ((write) && (buffer != NULL)) hideNeedles(buffer);
	return buffer;
}

void hideNeedles(char * buffer)
{
	char *ptr = &buffer[0];
	int index = 0;
	int iterations = KB / (needleLength + 1);

	for (int i = 0; i < iterations; i++)
	{
		memcpy(ptr, needle, needleLength);
		ptr += (needleLength + 1);
		plantedNeedles++;
	}
}

int FindNeedles()
{
	char *buffer = doMalloc();
	char *ptr = &buffer[0];
	char *MAX = &buffer[sizeof(buffer)];

	printf("Allocating Memory...");
	if (verbose) printf("\n");
	while (buffer != NULL)
	{
		if (&buffer[0] < ptr) ptr = &buffer[0];
		if (&buffer[sizeof(buffer)] > MAX) MAX = &buffer
[sizeof(buffer)];
		//MAX = &buffer[sizeof(buffer)];
		if (verbose) printf("\rMALLOC: &%p ", &buffer[0]);
		buffer = doMalloc();
	}
	if (verbose) printf("\n");
	printf("Done.  ");
	if (write) printf("%i needles planted.\n", plantedNeedles);
	if (!read) return 0;
	printf("\nFinding needles...");
	if (verbose) printf("\nNeedles found:\n0");
	int found = 0;

	while(ptr < MAX)
	{
		try
		{
			if(*ptr == needle[0])
			{
				if (memcmp(ptr, needle,
needleLength) == 0)
				{
					found++;
					if (verbose) printf("\r%
i", found);
					ptr += needleLength;
				}
				else
				{
					ptr++;
				}
			}
		}
		catch(...)
		{
			printf("\nError detected -- aborting.\n");
			break;
		}

		ptr++;
	}

	return found;
}

int SearchMemory(int offset)
{
	int count = offset;
	char *ptr = (char*)_x386_zero_base_ptr + count;
	for(int i = 0; i < 100000000; i++)
	{
		ptr = (char*)_x386_zero_base_ptr + count;
		printf("\r%i - (%c)", count, *ptr);
		count++;
	}
	return count;
}
/********************************/


Also, I can't seem to find any information that describes how to use a DOS 32-bit extender to my liking, so I'm still unsure if I'm going about this in the correct way.  Any input would be great!
April 02, 2007
You may need to allocate in several chunks to reach the limit due to limitations in the extender or underlying services (e.g., DPMI, VCPI) that it may be using.

Also, the allocation limit may have nothing to do with the actual true installed RAM available, even when the DOS extender does not provide virtual memory, other OS services might.  So you needs be careful about just what gets loaded or starts running, even on a CD-ROM boot.

So, is X32 running on bare metal?  Or does the CD-ROM boot disk load other things that may have a finger in the pie?  And just what is the DOS?  MS-DOS, DR-DOS, OpenDOS, FreeDOS or something else?  And what version?

I don't have experience with large core footprint issues in DOS extenders, so I have no specific help to give. Sorry.  But, IIRC, there were issues similar to those seen in 16 bit segmented addressing.
April 04, 2007
Hello,

Denzien wrote...
> 
> I've read that I can (possibly) address up to 3/4 of the available system memory using the x32 DOS extender, but my application can only malloc up to about 64MB.

The DOSX extender is rather old and seems to have a 64MB limit. In my DOS app I used the function _x32_allcoreleft() from X32.h to show me the available memory. I get about 62MB free memory when my app allocates about 2MB. It doesn't matter if the PC has 128MB, 256MB or even more! It doesn't make a difference if HIMEM is or isn't used.


- Heinz