Getting IP data from numerous sources

 

Basic information required to get for TCP/IP:

o The local machine's name

o The local machine's IP address(es)

o The IP addresses of DNS servers

Sample source code (in C), that demonstrate the techniques described in this 
document, are available on request.

This document refers seevral times to the Windows registry and to VxDs. If 
you want to use the registry and to call VxDs from within DOS programs
(running under Windows), also check out 
http://www.hoogervorst.demon.nl.no.spam/proteus/files/regdos.zip > (delete 
the usual no.spam from the URL).

Getting the local machine's name 
--------------------------------

You can get the computer's name by getting the ASCIIZ string from the 
following key:

HKEY_LOCAL_MACHINE\ 
System\ 
CurrentControlSet\ 
Control\ 
ComputerName\ 
ComputerName\ 
ComputerName = ASCIIZ string of max. 64 characters.

Several Windows TCP/IP programs use the computer name in host names, for 
example Eudora. However, the returned ASCIIZ string doesn't have to be 
"DNS compliant", i.e. it may have white space and other characters that 
are invalid in host names.

Alternatively, you can find the "real" machine name by getting the current 
IP address, and using gethostbyaddr().

RAS machines using some sort of dialup 
--------------------------------------

The RAS dialup adapter stores TCP/IP settings in a "phone book entry". For 
Windows 95, this phone book is stored in the registry. To get the relevant
addresses, you need to follow these steps:

1. Check if there's a RAS connection active (optional):

Read DWORD value of the following key:

HKEY_LOCAL_MACHINE\ 
System\ 
CurrentControlSet\ 
Services\ 
RemoteAccess\ 
Remote Connection = DWORD

If the returned DWORD has value 1, there's a RAS connection

2. Get the name of the current RAS phone book:

Read an ASCIIZ string from the following key:

HKEY_CURRENT_USER\ 
RemoteAccess\ 
Default = ASCIIZ string for the active phone book

The returned string should be used in the next step.

3. Get the RAS settings using the "phone book name". Note that you should 
first get the size for the settings buffer (using the Registry API).

Read binary data from the following key:

HKEY_CURRENT_USER\ 
RemoteAccess\ 
Profile\ 
"phone book name" = BINARY data of max. 50 bytes

"phone book name" is the name of the phone book retrieved in step 3.

4. The byte at offset 0x04 in the retrieved data buffer has several flags 
set for available TCP/IP data.

If bit one (0x01) is set, the user set a fixed IP address for the
current RAS connection. This fixed IP address (in host order) can
be found at offset 0x08.

If bit two (0x02) is set, the user specified one or two DNS addresses. 
The DNS addresses are in host order, and can be found at offset 0x0C 
and offset 0x10. Note: 0.0.0.0 (0x0UL) is an invalid (unspecified) DNS 
address.

History:

I had most of the registry functions working (for DOS programs running
under Windows 3.1 and 95), and also found the appropriate RAS connection 
key. I didn't find the necessary IP data, and told this to Jacob Verhoeks. 
The next day he came up with a full and detailed description of the binary 
data stored under the RemoteAccess\Profile tree.

Network machines 
----------------

For network machines too the data is stored in the registry. Here are the
steps to retrieve the current IP address and the DNS IP addresses.

1. The current active adapter's IP address can be found in the following key:

HKEY_LOCAL_MACHINE\ 
System\ 
CurrentControlSet\ 
Services\ 
Class\ 
NetTrans\ 
0000\ 
IPAddress = ASCIIZ string

This ASCIIZ string has the dotted name IP address.

Note: Presumably Windows 95 stores multiple interfaces in the NetTrans 
key. Ideally you should enumerate each of them, and check whether any 
of them has an "IPAddress" key.

2. The current IP addresses of DNS servers can be found in the following 
key:

HKEY_LOCAL_MACHINE\ 
System\ 
CurrentControlSet\ 
Services\ 
VxD\ 
MSTCP\ 
NameServer = ASCIIZ string

This key stores DNS IP addresses in a comma-separated list.

History:

I hadn't worked for a long time on DosSock95 when George Foot referred 
me to a .FIX file and sent me the info about the IP address. Both
George Foot and Jacob Verhoeks provided the key which stores the name 
server information.

Using the DHCP VxD to get the IP address and the DNS server data
----------------------------------------------------------------

For RAS connections, there's an alternate way to get the IP address and
DNS server addresses. This only works with RAS connections.

First get the entry point of the DHCP VxD (which has ID 0x49A). Call the 
entry point with (E)AX set to 1, ES:BX set to a buffer receiving DHCP data, 
and (E)CX with the size of the buffer. If the buffer is smaller than the 
data available, AX will be set to 111 (Win32 error: ERROR_BUFFER_OVERFLOW) 
and the first DWORD in the buffer will contain the size of the DHCP data.

Here's how the information looks like:

Offset   Type       What

0x0000   WORD       Number of IP addresses 
0x000C   DWORD      IP addresses in host order 
0x0020   WORD       Total number of bytes in server addresses. Divide by 
four to get the number of server addresses. 
0x0024   WORD       Offset (from begin of data) to server addresses.

History:

This information was found while stepping through the WinSock code.
Don't try this at home (in a sense: do it actually at home).

Using WsControl() to get the IP address
---------------------------------------

WsControl() is an undocumented function found in both the 16 bit and the 
32 bit WinSock DLLs of Microsoft. Many people already suspected that 
WsControl() returns very useful data, because it's used by the Windows 95 
WINIPCFG tool. The problem is that it's an undocumented function: you won't 
hear anything of it from Microsoft... In short: the following information may
be highly platform dependent, and extremely unportable. Food for the hacking 
minded proper. Here's what I found out (and I'd appreciate any comments if 
you find other things about WsControl).

The WsControl() function looks like this:

DWORD WsControl(DWORD Protocol, DWORD Action, 
LPVOID CommandBuffer, LPDWORD CommandBufferSize, 
LPVOID ResultBuffer, LPDWORD ResultBufferSize);

For TCP/IP Protocol should be set to IPPROTO_TCP and/or IPPROTO_UDP. Other 
protocol values result in the expected WSA error "unsupported protocol".

The only value of Action I encountered was 0, which seems to mean something 
like "Get Information". I believe that passing a value of 1 would send
something like "Set Information" to WinSock; but I must admit that I didn't
try this. (For obvious reasons ofcourse. If you happen to have a lot of 
money, consider donating money to me, so I can buy a test machine. :-)

CommandBuffer has a buffer with a command that's sent to WinSock, 
CommandBufferSize points to a DWORD with the size of the CommandBuffer.

On return of the function, ResultBuffer will have data returned by WsControl 
for the command in CommandBuffer. The DWORD pointed to by ResultBufferSize 
should have the size of ResultBuffer on function call, and has the number
of bytes written to ResultBuffer on function return.

CommandBuffer 
-------------

The Command buffer is a structure of 36 bytes. It may look like this; names 
are mine, yours may be better.

#pragma pack(1) 
typedef struct 

DWORD Number;  /* Interface number, WS_INTERFACE_TCPIP for TCPIP */ 
DWORD Unknown; /* Seems to be used to differentiate between 
* multiple TCPIP interfaces. */ 
} WS_INTERFACE, FAR* LPWS_INTERFACE, NEAR* NPWS_INTERFACE, * PWS_INTERFACE;

typedef struct 

WS_INTERFACE Interface;     /* Interfaces to query???      */

DWORD        What;          /* Changes for each request    */ 
DWORD        Unknown;       /* Seems to be always 0x100??? */ 
DWORD        Command;       /* Obviously a command         */

BYTE         Unknown1[16];  /* Unknown (Always 0???)       */ 
} WS_IN_PARAMS, FAR* LPWS_IN_PARAMS, NEAR* NPWS_IN_PARAMS, * PWS_IN_PARAMS; 
#pragma pack()

The first two DWORDs in the WS_IN_PARAMS structure (the CommandBuffer) have 
a number for what I call an "interface". In Windows 95 lingo you can call 
it an adapter. For the TCP/IP interface, the Interface should have a value 
of 0x0301, with possibly some other value for the most significant DWORD 
(little endian: xxxx xxxx 0000 0301).

Just to clarify the above phrase: when Windows searches 
for an TCP/IP interface, it loops while checking for the 
DWORD 0x00000301.

The What member seems to change for each WsControl request, and probably 
"browses" deeper into the hierarchy of data available through WsControl.

The Command member has a number which seem to correspond with a command.

Available Commands 
------------------

Here's what I found about commands. Note that the naming of the commands 
are mine; yours may be better.

Get List Of Interfaces 
----------------------

Interface  = 0 
What       = 0x100 
Unknown    = 0x100 
Command    = 0 
Unknown1[] = 0

Returns several quad words (4 words, 2 dwords) with all the interfaces 
available for use in WsControl.

The interface number for TCP/IP is 0x0301 (with the Unknown dword 
possibly set to differentiate between multiple TCP/IP interfaces).

Example output:

0000: 00 04 00 00 00 00 00 00 - 01 04 00 00 00 00 00 00 
0010: 01 03 00 00 00 00 00 00 - 80 03 00 00 00 00 00 00 
0020: 80 02 00 00 00 00 00 00 - 00 02 00 00 00 00 00 00 
0030: 00 02 00 00 01 00 00 00

The quadword at offset 0x10 has the first (and only) TCP/IP interface. 
Incidently, the quadword at 0x30 is related to the loopback adapter, 
the quadword at 0x28 to the PPP adapter.

Acknowledge Valid Interface (Get Version??? Is Current???) 
----------------------------------------------------------

Interface  = Valid Interface 
What       = 0x100 
Unknown    = 0x100 
Command    = 0x1 
Unknown1[] = 0

To acknowledge the interface in Interface, send the above command. 
The result buffer should return a DWORD with a special value.

For example, the interface number for TCP/IP is 0x0301. If you set 
Interface to 0000 0000 0000 0301, the returned DWORD will contain 
0x0303. Presumably, the special value returned is related to the 
HIBYTE of the interface number.

Note that the ResultBufferSize will NOT have the number of bytes written 
to the buffer. This seems to be a bug - or perhaps it's just the way 
this command is supposed to work. Your guess may be better.

Example output:

0000: 03 03 00 00

The above output is for the TCP/IP interface.

Get Interface Information 
-------------------------

Interface  = Valid Interface 
What       = 0x200 
Unknown    = 0x100 
Command    = 0x1 
Unknown1[] = 0

This command returns several data which may or may not be useful at all.

For TCP/IP the DWORD at offset 0x54 has the number of IP addresses 
active for the TCP/IP interface. To get specific IP address information, 
use the Get Active Address Information.

For TCP/IP the DWORD at offset 0x58 has the number of IP address related 
information structures. To get the information, use the Get Extended Active 
Address Information.

Example Output:

For TCP/IP:

0000: 02 00 00 00 80 00 00 00 - EA 01 00 00 00 00 00 00 
0010: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 
0020: EA 01 00 00 66 01 00 00 - 00 00 00 00 00 00 00 00 
0030: 00 00 00 00 3C 00 00 00 - 00 00 00 00 00 00 00 00 
0040: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 
0050: 02 00 00 00 02 00 00 00 - 07 00 00 00

The DWORD at offset 0x54 has the number of structures returned by 
the Get Active Address Information command. The DWORD at offset 
0x58 has the number of structures returned by the Get Extended 
Active Address command.

Get Extended Active Address Information 
---------------------------------------

Interface  = Valid Interface 
What       = 0x200 
Unknown    = 0x100 
Command    = 0x101 
Unknown1[] = 0

For TCP/IP this command returns data with an unknown structure. It 
seems to list network masks.

Example output:

For TCP/IP see output below. Note that the size of each structure is 
0x150 / 0x07.

0000: E0 00 00 00 02 00 00 00 - 01 00 00 00 FF FF FF FF 
0010: FF FF FF FF FF FF FF FF - C3 AD E4 8E 03 00 00 00 
0020: 02 00 00 00 38 00 00 00 - E0 00 00 00 FF FF FF FF 
0030: 00 00 00 00 02 00 00 00 - 01 00 00 00 FF FF FF FF 
0040: FF FF FF FF FF FF FF FF - C3 AD E4 8E 03 00 00 00 
0050: 02 00 00 00 38 00 00 00 - 00 00 00 00 FF FF FF FF 
0060: C3 AD E4 8E 01 00 00 00 - 01 00 00 00 FF FF FF FF 
0070: FF FF FF FF FF FF FF FF - 7F 00 00 01 03 00 00 00 
0080: 02 00 00 00 38 00 00 00 - FF FF FF FF FF FF FF FF 
0090: C3 AD E4 FF 02 00 00 00 - 01 00 00 00 FF FF FF FF 
00A0: FF FF FF FF FF FF FF FF - C3 AD E4 8E 03 00 00 00 
00B0: 02 00 00 00 38 00 00 00 - FF FF FF FF FF FF FF FF 
00C0: C3 AD E4 00 02 00 00 00 - 01 00 00 00 FF FF FF FF 
00D0: FF FF FF FF FF FF FF FF - C3 AD E4 8E 03 00 00 00 
00E0: 02 00 00 00 38 00 00 00 - FF FF FF 00 FF FF FF FF 
00F0: FF FF FF FF 02 00 00 00 - 01 00 00 00 FF FF FF FF 
0100: FF FF FF FF FF FF FF FF - C3 AD E4 8E 03 00 00 00 
0110: 02 00 00 00 BB 2B 00 00 - FF FF FF FF FF FF FF FF 
0120: 7F 00 00 00 01 00 00 00 - 01 00 00 00 FF FF FF FF 
0130: FF FF FF FF FF FF FF FF - 7F 00 00 01 03 00 00 00 
0140: 02 00 00 00 BC 2B 00 00 - FF 00 00 00 FF FF FF FF

Get Active Address Information 
------------------------------

Interface  = Valid Interface 
What       = 0x200 
Unknown    = 0x100 
Command    = 0x102 
Unknown1[] = 0

For TCP/IP this command returns data which is partly understood. The 
first four bytes in each structure have active IP addresses.

Example output:

For TCP/IP see output below. Note that the size of each structure is 
0x30 / 0x02.

0000: C3 AD E4 8E 02 00 00 00 - FF FF FF 00 01 00 00 00 
0010: FF FF 00 00 01 00 00 C0 - 7F 00 00 01 01 00 00 00 
0020: FF 00 00 00 01 00 00 00 - FF FF 00 00 00 00 00 C0

As you can see, the first DWORD has the current IP address 
(195.173.228.142). The first DWORD in the second structure has the 
loopback address of 127.0.0.1, which was active at that time.

Author 
------

Written by Alfons Hoogervorst. He can be contacted at 
<alfonsAThoogervorstDOTdemonDOTnl>.

If you have additional information about any of the topics in this document, 
especially about WsControl(), send me a note. Comments, suggestions, and 
any useful hints are welcome too.

Alfons works as a freelance developer, specializing in low-level programming.

Legalese 
--------

You're allowed to distribute this file for free, without paying me any fee. 
However, the following sections should remain unmodified in this document:

Introduction, Author, Legalese, Copyright.

The information in this document is provided AS IS, without any warranties 
or guarantees. As a human being, he expressedly reserves his rights to err: 
"If its meaning doesn't manifest, then: put it to rest!"

Copyright 
---------

Copyright (C) Alfons Hoogervorst / The Programming with Puns Facility, 1998

 


GSO
Written on Saturday, 03 October 2009 17:37 by GSO

Viewed 125 times so far.
Like this? Tweet it to your followers!

Rate this article

Latest articles from GSO

Latest 'tweets' from GovernmentSecurity

  • Can I get a Hoot Hoot?! #HootSuite is my number one Twitter client. http://hootsuite.com Link Friday, 06 November 2009 06:03
  • @foadah Thas what Im talking about :) Link Friday, 06 November 2009 05:58
  • #security | Don't panic over the secret copyright treaty | latest-security-news | GSO - Network Security Resources http://bit.ly/1K63Sr Link Thursday, 05 November 2009 08:01
  • #security | Which country has the most bot-infected computers? | latest-security-news | GSO - Network Security Reso... http://bit.ly/HAeG9 Link Thursday, 05 November 2009 08:01
  • #security | Backdoor access for millions of Facebook and MySpace accounts | latest-security-news | GSO - Network S... http://bit.ly/3dwnmc Link Thursday, 05 November 2009 08:01
blog comments powered by Disqus

Site Search

Sponsor Advertisements

SwiftLayer Affiliate Web Hosting

Disqus Tools