From b4e52e6b45abe2802431b95ca2fbdf55691bf7e2 Mon Sep 17 00:00:00 2001
From: Jason Hood <jadoxa@yahoo.com.au>
Date: Sat, 4 Dec 2010 15:19:36 +1000
Subject: [PATCH] Fix crashes

---
 ANSI.c      | 83 ++++++++++++-----------------------------------------
 ansi.rc     |  8 +++---
 ansicon.c   | 50 +++++++++++++++++++++-----------
 ansicon.rc  |  8 +++---
 injdll.h    |  1 +
 injdll32.c  |  2 +-
 makefile    | 14 ++++-----
 makefile.vc |  8 +++---
 proctype.c  | 64 +++++++++++++++++++++++++++++++++++++++++
 9 files changed, 138 insertions(+), 100 deletions(-)
 create mode 100644 proctype.c

diff --git a/ANSI.c b/ANSI.c
index a58714a..6f4bff3 100644
--- a/ANSI.c
+++ b/ANSI.c
@@ -56,6 +56,9 @@
 
   v1.31, 13 November, 2010:
     fix multibyte conversion problems.
+
+  v1.32, 4 December, 2010:
+    test for lpNumberOfCharsWritten/lpNumberOfBytesWritten being NULL.
 */
 
 #ifndef UNICODE
@@ -76,9 +79,9 @@
 
 // ========== Auxiliary debug function
 
-//#define MYDEBUG 0			// no debugging
+#define MYDEBUG 0			// no debugging
 //#define MYDEBUG 1			// use OutputDebugString
-#define MYDEBUG 2			// use %temp%\ansicon.log
+//#define MYDEBUG 2			// use %temp%\ansicon.log
 
 #if (MYDEBUG > 0)
 #if (MYDEBUG > 1)
@@ -135,7 +138,7 @@ void DEBUGSTR( LPTSTR szFormat, ... )	// sort of OutputDebugStringf
   }
 #if (MYDEBUG > 1)
   {
-  FILE* file = fopen( tempfile, "a" );
+  FILE* file = fopen( tempfile, "at" ); // _fmode might be binary
   if (file != NULL)
   {
     fwprintf( file, L"%s\n", szFormat );
@@ -877,7 +880,8 @@ ParseAndPrintString( HANDLE hDev,
     }
   }
   FlushBuffer();
-  *lpNumberOfBytesWritten = nNumberOfBytesToWrite - i;
+  if (lpNumberOfBytesWritten != NULL)
+    *lpNumberOfBytesWritten = nNumberOfBytesToWrite - i;
   return( i == 0 );
 }
 
@@ -888,69 +892,14 @@ ParseAndPrintString( HANDLE hDev,
 void Inject( LPPROCESS_INFORMATION pinfo, LPPROCESS_INFORMATION lpi,
 	     DWORD dwCreationFlags )
 {
-  char* ptr = 0;
-  MEMORY_BASIC_INFORMATION minfo;
-  BOOL	con = FALSE;
-#ifdef _WIN64
-  BOOL	x86 = FALSE;
-#endif
-
-  while (VirtualQueryEx( pinfo->hProcess, ptr, &minfo, sizeof(minfo) ))
-  {
-    IMAGE_DOS_HEADER dos_header;
-    SIZE_T read;
-    if (ReadProcessMemory( pinfo->hProcess, minfo.AllocationBase,
-			   &dos_header, sizeof(dos_header), &read ))
-    {
-      if (dos_header.e_magic == IMAGE_DOS_SIGNATURE)
-      {
-	IMAGE_NT_HEADERS nt_header;
-	if (ReadProcessMemory( pinfo->hProcess, (char*)minfo.AllocationBase +
-			       dos_header.e_lfanew, &nt_header,
-			       sizeof(nt_header), &read ))
-	{
-	  if (nt_header.Signature == IMAGE_NT_SIGNATURE)
-	  {
-	    if (nt_header.OptionalHeader.Subsystem ==
-						   IMAGE_SUBSYSTEM_WINDOWS_CUI)
-	    {
-	      if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
-	      {
-		con = TRUE;
-#ifdef _WIN64
-		x86 = TRUE;
-	      }
-	      else if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
-	      {
-		con = TRUE;
-#endif
-	      }
-	      else
-	      {
-		DEBUGSTR( L"  Ignoring unsupported machine (%x)",
-			  nt_header.FileHeader.Machine );
-	      }
-	    }
-	    else
-	    {
-	      DEBUGSTR( L"  Ignoring non-console subsystem (%u)",
-			nt_header.OptionalHeader.Subsystem );
-	    }
-	    break;
-	  }
-	}
-      }
-    }
-    ptr += minfo.RegionSize;
-  }
-
-  if (con)
+  int type = ProcessType( pinfo );
+  if (type != 0)
   {
     WCHAR dll[MAX_PATH];
 #ifdef _WIN64
     DWORD len = GetModuleFileName( GetModuleHandleA( "ANSI64.dll" ),
 				   dll, lenof(dll) );
-    if (x86)
+    if (type == 32)
     {
       dll[len-6] = '3';
       dll[len-5] = '2';
@@ -965,6 +914,11 @@ void Inject( LPPROCESS_INFORMATION pinfo, LPPROCESS_INFORMATION lpi,
     InjectDLL32( pinfo, dll );
 #endif
   }
+  else
+  {
+    DEBUGSTR( L"  Unsupported process type" );
+  }
+
 
   if (lpi)
     memcpy( lpi, pinfo, sizeof(PROCESS_INFORMATION) );
@@ -1117,7 +1071,8 @@ WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
     buf = malloc( len * sizeof(WCHAR) );
     if (buf == NULL)
     {
-      *lpNumberOfCharsWritten = 0;
+      if (lpNumberOfCharsWritten != NULL)
+	*lpNumberOfCharsWritten = 0;
       return (nNumberOfCharsToWrite == 0);
     }
     MultiByteToWideChar( cp, 0, lpBuffer, nNumberOfCharsToWrite, buf, len );
@@ -1163,7 +1118,7 @@ WINAPI MyWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
   DWORD Mode;
   if (GetConsoleMode( hFile, &Mode ) && (Mode & ENABLE_PROCESSED_OUTPUT))
   {
-    DEBUGSTR( L"\\WriteFile: %lu \"%.*S\"", nNumberOfBytesToWrite, nNumberOfBytesToWrite, lpBuffer );
+    DEBUGSTR( L"WriteFile->" );
     return MyWriteConsoleA( hFile, lpBuffer,
 			    nNumberOfBytesToWrite,
 			    lpNumberOfBytesWritten,
diff --git a/ansi.rc b/ansi.rc
index 3604dac..3aedb28 100644
--- a/ansi.rc
+++ b/ansi.rc
@@ -13,8 +13,8 @@
 #endif
 
 1 VERSIONINFO
-FILEVERSION	1,3,1,0
-PRODUCTVERSION	1,3,1,0
+FILEVERSION	1,3,2,0
+PRODUCTVERSION	1,3,2,0
 FILEOS		VOS_NT
 FILETYPE	VFT_DLL
 {
@@ -25,12 +25,12 @@ FILETYPE	VFT_DLL
       VALUE "Comments",         "http://ansicon.adoxa.cjb.net/"
       VALUE "CompanyName",      "Jason Hood"
       VALUE "FileDescription",  "ANSI Console"
-      VALUE "FileVersion",      "1.31"
+      VALUE "FileVersion",      "1.32"
       VALUE "InternalName",     "ANSI" BITS
       VALUE "LegalCopyright",   "Freeware"
       VALUE "OriginalFilename", "ANSI" BITS ".dll"
       VALUE "ProductName",      "ANSICON"
-      VALUE "ProductVersion",   "1.31"
+      VALUE "ProductVersion",   "1.32"
     }
   }
 
diff --git a/ansicon.c b/ansicon.c
index 8b103be..3e0f90e 100644
--- a/ansicon.c
+++ b/ansicon.c
@@ -42,10 +42,13 @@
     use LLW to fix potential Unicode path problems;
     VC compatibility (2008 Express for 32-bit, PSDK 2003 R2 for 64-bit);
     explicitly use wide characters (stick with TCHAR, but not <tchar.h>).
+
+  v1.32, 4 December, 2010:
+    make -p more robust.
 */
 
-#define PVERS L"1.31"
-#define PDATE L"15 November, 2010"
+#define PVERS L"1.32"
+#define PDATE L"4 December, 2010"
 
 #ifndef UNICODE
 # define UNICODE
@@ -70,11 +73,9 @@ int _CRT_glob = 0;
 
 
 #ifdef _WIN64
-# define InjectDLL InjectDLL64
-# define BITS	   L"64"
+# define BITS L"64"
 #else
-# define InjectDLL InjectDLL32
-# define BITS	   L"32"
+# define BITS L"32"
 #endif
 
 
@@ -82,30 +83,43 @@ int _CRT_glob = 0;
 #define AUTORUN L"AutoRun"
 
 
-void help( void );
+void   help( void );
 
 void   display( LPCTSTR, BOOL );
 LPTSTR skip_spaces( LPTSTR );
 LPTSTR skip_arg( LPTSTR );
 
-void process_autorun( TCHAR );
+void   process_autorun( TCHAR );
 
-BOOL find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe );
-BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi );
+BOOL   find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe );
+BOOL   GetParentProcessInfo( LPPROCESS_INFORMATION ppi );
 
 
 // Find the name of the DLL and inject it.
-void Inject( LPPROCESS_INFORMATION ppi )
+BOOL Inject( LPPROCESS_INFORMATION ppi )
 {
   DWORD len;
-  TCHAR dll[MAX_PATH];
+  WCHAR dll[MAX_PATH];
+  int	type;
+
+  type = ProcessType( ppi );
+  if (type == 0)
+    return FALSE;
 
   len = GetModuleFileName( NULL, dll, lenof(dll) );
   while (dll[len-1] != '\\')
     --len;
-  lstrcpy( dll + len, L"ANSI" BITS L".dll" );
-
-  InjectDLL( ppi, dll );
+#ifdef _WIN64
+  swprintf( dll + len, L"ANSI%d.dll", type );
+  if (type == 32)
+    InjectDLL32( ppi, dll );
+  else
+    InjectDLL64( ppi, dll );
+#else
+  wcscpy( dll + len, L"ANSI32.dll" );
+  InjectDLL32( ppi, dll );
+#endif
+  return TRUE;
 }
 
 
@@ -210,7 +224,11 @@ int main( void )
       pi.hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId );
       pi.hThread  = OpenThread(  THREAD_ALL_ACCESS,  FALSE, pi.dwThreadId  );
       SuspendThread( pi.hThread );
-      Inject( &pi );
+      if (!Inject( &pi ))
+      {
+	_putws( L"ANSICON: parent process type is not supported." );
+	rc = 1;
+      }
       ResumeThread( pi.hThread );
       CloseHandle( pi.hThread );
       CloseHandle( pi.hProcess );
diff --git a/ansicon.rc b/ansicon.rc
index deb2999..d87cde3 100644
--- a/ansicon.rc
+++ b/ansicon.rc
@@ -7,8 +7,8 @@
 #include <winver.h>
 
 1 VERSIONINFO
-FILEVERSION	1,3,1,0
-PRODUCTVERSION	1,3,1,0
+FILEVERSION	1,3,2,0
+PRODUCTVERSION	1,3,2,0
 FILEOS		VOS_NT
 FILETYPE	VFT_APP
 {
@@ -19,12 +19,12 @@ FILETYPE	VFT_APP
       VALUE "Comments",         "http://ansicon.adoxa.cjb.net/"
       VALUE "CompanyName",      "Jason Hood"
       VALUE "FileDescription",  "ANSI Console"
-      VALUE "FileVersion",      "1.31"
+      VALUE "FileVersion",      "1.32"
       VALUE "InternalName",     "ansicon"
       VALUE "LegalCopyright",   "Freeware"
       VALUE "OriginalFilename", "ansicon.exe"
       VALUE "ProductName",      "ANSICON"
-      VALUE "ProductVersion",   "1.31"
+      VALUE "ProductVersion",   "1.32"
     }
   }
 
diff --git a/injdll.h b/injdll.h
index 171f3a6..7f02ca7 100644
--- a/injdll.h
+++ b/injdll.h
@@ -14,6 +14,7 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
+BOOL ProcessType( LPPROCESS_INFORMATION );
 void InjectDLL32( LPPROCESS_INFORMATION, LPCTSTR );
 void InjectDLL64( LPPROCESS_INFORMATION, LPCTSTR );
 
diff --git a/injdll32.c b/injdll32.c
index 34790b4..f7dbff3 100644
--- a/injdll32.c
+++ b/injdll32.c
@@ -59,7 +59,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
   {
 #ifdef _WIN64
 #ifdef __MINGW64__
-    extern HMODULE hKernel;
+    HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
     #define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
     GETPROC( Wow64GetThreadContext );
     GETPROC( Wow64SetThreadContext );
diff --git a/makefile b/makefile
index 6f0d86a..8cf2c2d 100644
--- a/makefile
+++ b/makefile
@@ -15,7 +15,7 @@ x86/%v.o: %.rc
 	windres -U _WIN64 -F pe-i386 $< $@
 
 x64/%.o: %.c
-	$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+	$(CC) -m64 -c $(CFLAGS) $(CPPFLAGS) $< -o $@
 
 x64/%v.o: %.rc
 	windres $< $@
@@ -29,20 +29,20 @@ ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll x64/ANSI-LLW.exe
 x86:
 	mkdir x86
 
-x86/ansicon.exe: x86/ansicon.o x86/injdll32.o x86/ansiconv.o
+x86/ansicon.exe: x86/ansicon.o x86/proctype.o x86/injdll32.o x86/ansiconv.o
 	$(CC) -m32 $+ -s -o $@
 
-x86/ANSI32.dll: x86/ANSI.o x86/injdll32.o x86/ansiv.o
+x86/ANSI32.dll: x86/ANSI.o x86/proctype.o x86/injdll32.o x86/ansiv.o
 	$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared
 
 x64:
 	mkdir x64
 
-x64/ansicon.exe: x64/ansicon.o x64/injdll64.o x64/ansiconv.o
-	$(CC) $+ -s -o $@
+x64/ansicon.exe: x64/ansicon.o x64/proctype.o x64/injdll64.o x64/injdll32.o x64/ansiconv.o
+	$(CC) -m64 $+ -s -o $@
 
-x64/ANSI64.dll: x64/ANSI.o x64/injdll64.o x64/injdll32.o x64/ansiv.o
-	$(CC) $+ -s -o $@ -mdll -Wl,-shared
+x64/ANSI64.dll: x64/ANSI.o x64/proctype.o x64/injdll64.o x64/injdll32.o x64/ansiv.o
+	$(CC) -m64 $+ -s -o $@ -mdll -Wl,-shared
 
 x64/ANSI32.dll: x86/ANSI32.dll
 	cp -p x86/ANSI32.dll x64/ANSI32.dll
diff --git a/makefile.vc b/makefile.vc
index 1face60..3b1413d 100644
--- a/makefile.vc
+++ b/makefile.vc
@@ -43,10 +43,10 @@ ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll x64\ANSI32.dll x64\ANSI-LLW.exe
 x86:
 	mkdir x86
 
-x86\ansicon.exe: x86\ansicon.obj x86\injdll32.obj x86\ansicon.res
+x86\ansicon.exe: x86\ansicon.obj x86\proctype.obj x86\injdll32.obj x86\ansicon.res
 	$(CC) /nologo /Fe$@ $** $(LIBS)
 
-x86\ANSI32.dll: x86\ANSI.obj x86\injdll32.obj x86\ansi.res
+x86\ANSI32.dll: x86\ANSI.obj x86\proctype.obj x86\injdll32.obj x86\ansi.res
 !IF $(BITS) == 32
 	$(CC) /nologo /LD /Fe$@ $** $(LIBS)
 !ENDIF
@@ -54,10 +54,10 @@ x86\ANSI32.dll: x86\ANSI.obj x86\injdll32.obj x86\ansi.res
 x64:
 	mkdir x64
 
-x64\ansicon.exe: x64\ansicon.obj x64\injdll64.obj x64\ansicon.res
+x64\ansicon.exe: x64\ansicon.obj x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\ansicon.res
 	$(CC) /nologo /Fe$@ $** $(LIBS) bufferoverflowu.lib
 
-x64\ANSI64.dll: x64\ANSI.obj x64\injdll64.obj x64\injdll32.obj x64\ansi.res
+x64\ANSI64.dll: x64\ANSI.obj x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\ansi.res
 	$(CC) /nologo /LD /Fe$@ $** $(LIBS) bufferoverflowu.lib
 
 x64\ANSI32.dll: x86\ANSI32.dll
diff --git a/proctype.c b/proctype.c
new file mode 100644
index 0000000..cf84f7f
--- /dev/null
+++ b/proctype.c
@@ -0,0 +1,64 @@
+/*
+  Test for a valid process.
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+
+int ProcessType( LPPROCESS_INFORMATION pinfo )
+{
+  MEMORY_BASIC_INFORMATION minfo;
+  char* ptr = 0;
+  int	type = 0;
+
+  while (VirtualQueryEx( pinfo->hProcess, ptr, &minfo, sizeof(minfo) ))
+  {
+    IMAGE_DOS_HEADER dos_header;
+    SIZE_T read;
+    if (ReadProcessMemory( pinfo->hProcess, minfo.AllocationBase,
+			   &dos_header, sizeof(dos_header), &read ))
+    {
+      if (dos_header.e_magic == IMAGE_DOS_SIGNATURE)
+      {
+	IMAGE_NT_HEADERS nt_header;
+	if (ReadProcessMemory( pinfo->hProcess, (char*)minfo.AllocationBase +
+			       dos_header.e_lfanew, &nt_header,
+			       sizeof(nt_header), &read ))
+	{
+	  if (nt_header.Signature == IMAGE_NT_SIGNATURE)
+	  {
+	    if (nt_header.OptionalHeader.Subsystem ==
+						   IMAGE_SUBSYSTEM_WINDOWS_CUI)
+	    {
+	      if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
+	      {
+		type = 32;
+#ifdef _WIN64
+	      }
+	      else if (nt_header.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
+	      {
+		type = 64;
+#endif
+	      }
+	      else
+	      {
+		//DEBUGSTR( L"  Ignoring unsupported machine (%x)",
+		//	  nt_header.FileHeader.Machine );
+	      }
+	    }
+	    else
+	    {
+	      //DEBUGSTR( L"  Ignoring non-console subsystem (%u)",
+	      //	nt_header.OptionalHeader.Subsystem );
+	    }
+	    break;
+	  }
+	}
+      }
+    }
+    ptr += minfo.RegionSize;
+  }
+
+  return type;
+}