From 1fc43d46c330ca0009c846430fa19ce56643be77 Mon Sep 17 00:00:00 2001 From: Jason Hood Date: Fri, 19 Jul 2013 00:14:54 +1000 Subject: [PATCH] Remove ANSI-LLW.exe for good; tweak makefiles & doc; release v1.62. --- ANSI-LLW.asm | 23 --- ANSI-LLW.c | 22 --- ANSI.c | 3 + COPYING.MinGW-w64-runtime.txt | 240 ---------------------------- ansi.rc | 12 +- ansicon.c | 64 ++++++-- ansicon.rc | 22 ++- injdll32.c | 200 ++++++++++++++++++++---- makefile | 85 ---------- makefile.gcc | 112 +++++++++++++ makefile.vc | 79 +++++++--- readme.txt | 285 ++++++++++++++++------------------ util.c | 2 +- version.h | 20 ++- 14 files changed, 561 insertions(+), 608 deletions(-) delete mode 100644 ANSI-LLW.asm delete mode 100644 ANSI-LLW.c delete mode 100644 COPYING.MinGW-w64-runtime.txt delete mode 100644 makefile create mode 100644 makefile.gcc diff --git a/ANSI-LLW.asm b/ANSI-LLW.asm deleted file mode 100644 index e26cc61..0000000 --- a/ANSI-LLW.asm +++ /dev/null @@ -1,23 +0,0 @@ -; ANSI-LLW.asm - Output the 32-bit address of LoadLibraryW. -; -; Jason Hood, 1 February, 2013. -; -; A FASM (flatassembler.net) version of the C code, which virus scanners didn't -; like for some reason. - - -format PE Console 4.0 - -include 'win32a.inc' - - mov eax, [LoadLibraryW] - ret - -data import - - library kernel32,'KERNEL32.DLL' - - import kernel32,\ - LoadLibraryW,'LoadLibraryW' - -end data diff --git a/ANSI-LLW.c b/ANSI-LLW.c deleted file mode 100644 index 28991f0..0000000 --- a/ANSI-LLW.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - ANSI-LLW.c - Output the 32-bit address of LoadLibraryW. - - Jason Hood, 13 November, 2010 (LLA version 5 September, 2010). - - I don't know of a method to retrieve the 32-bit address of a function in - 64-bit code, so this is a simple workaround. - - 18 December, 2010: Initially I used GetProcAddress, but then I thought that - was silly, why don't I just return LoadLibraryW directly? That worked fine - for TDM64 and VC, but MinGW32 would return the address of the jump to the - function, not the function itself. Not so silly after all. -*/ - -#define WIN32_LEAN_AND_MEAN -#include - -int main( void ) -{ - return (DWORD)GetProcAddress( GetModuleHandle( "kernel32.dll" ), - "LoadLibraryW" ); -} diff --git a/ANSI.c b/ANSI.c index dc19cbb..a0b3e82 100644 --- a/ANSI.c +++ b/ANSI.c @@ -98,6 +98,9 @@ v1.61, 14 February, 2013: go back to using ANSI-LLW.exe for 64->32 injection. + + v1.62, 17 & 18 July, 2013: + another method to obtain LLW for 64->32 injection. */ #include "ansicon.h" diff --git a/COPYING.MinGW-w64-runtime.txt b/COPYING.MinGW-w64-runtime.txt deleted file mode 100644 index 3d11e87..0000000 --- a/COPYING.MinGW-w64-runtime.txt +++ /dev/null @@ -1,240 +0,0 @@ -MinGW-w64 runtime licensing -*************************** - -This program or library was built using MinGW-w64 and statically -linked against the MinGW-w64 runtime. Some parts of the runtime -are under licenses which require that the copyright and license -notices are included when distributing the code in binary form. -These notices are listed below. - - -======================== -Overall copyright notice -======================== - -Copyright (c) 2009, 2010 by the mingw-w64 project - -This license has been certified as open source. It has also been designated -as GPL compatible by the Free Software Foundation (FSF). - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions in source code must retain the accompanying copyright - notice, this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the accompanying - copyright notice, this list of conditions, and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - 3. Names of the copyright holders must not be used to endorse or promote - products derived from this software without prior written permission - from the copyright holders. - 4. The right to distribute this software or to use it for any purpose does - not give you the right to use Servicemarks (sm) or Trademarks (tm) of - the copyright holders. Use of them is covered by separate agreement - with the copyright holders. - 5. If any files are modified, you must cause the modified files to carry - prominent notices stating that you changed the files and the date of - any change. - -Disclaimer - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -======================================== -getopt, getopt_long, and getop_long_only -======================================== - -Copyright (c) 2002 Todd C. Miller - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Sponsored in part by the Defense Advanced Research Projects -Agency (DARPA) and Air Force Research Laboratory, Air Force -Materiel Command, USAF, under agreement number F39502-99-1-0512. - - * * * * * * * - -Copyright (c) 2000 The NetBSD Foundation, Inc. -All rights reserved. - -This code is derived from software contributed to The NetBSD Foundation -by Dieter Baron and Thomas Klausner. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -=============================================================== -gdtoa: Converting between IEEE floating point numbers and ASCII -=============================================================== - -The author of this software is David M. Gay. - -Copyright (C) 1997, 1998, 1999, 2000, 2001 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - - * * * * * * * - -The author of this software is David M. Gay. - -Copyright (C) 2005 by David M. Gay -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that the copyright notice and this permission notice and warranty -disclaimer appear in supporting documentation, and that the name of -the author or any of his current or former employers not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN -NO EVENT SHALL THE AUTHOR OR ANY OF HIS CURRENT OR FORMER EMPLOYERS BE -LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - - * * * * * * * - -The author of this software is David M. Gay. - -Copyright (C) 2004 by David M. Gay. -All Rights Reserved -Based on material in the rest of /netlib/fp/gdota.tar.gz, -which is copyright (C) 1998, 2000 by Lucent Technologies. - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - - -========================= -Parts of the math library -========================= - -Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - -Developed at SunSoft, a Sun Microsystems, Inc. business. -Permission to use, copy, modify, and distribute this -software is freely granted, provided that this notice -is preserved. - - * * * * * * * - -Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - -Developed at SunPro, a Sun Microsystems, Inc. business. -Permission to use, copy, modify, and distribute this -software is freely granted, provided that this notice -is preserved. - - * * * * * * * - -FIXME: Cephes math lib -Copyright (C) 1984-1998 Stephen L. Moshier - -It sounds vague, but as to be found at -, it gives an -impression that the author could be willing to give an explicit -permission to distribute those files e.g. under a BSD style license. So -probably there is no problem here, although it could be good to get a -permission from the author and then add a license into the Cephes files -in MinGW runtime. At least on follow-up it is marked that debian sees the -version a-like BSD one. As MinGW.org (where those cephes parts are coming -from) distributes them now over 6 years, it should be fine. - -=================================== -Headers and IDLs imported from Wine -=================================== - -Some header and IDL files were imported from the Wine project. These files -are prominent maked in source. Their copyright belongs to contributors and -they are distributed under LGPL license. - -Disclaimer - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. diff --git a/ansi.rc b/ansi.rc index 16a4585..cf20af4 100644 --- a/ansi.rc +++ b/ansi.rc @@ -7,13 +7,7 @@ #include #include "version.h" -#ifdef _WIN64 -# define BITS "64" -#else -# define BITS "32" -#endif - -1 VERSIONINFO +VS_VERSION_INFO VERSIONINFO FILEVERSION PVERB PRODUCTVERSION PVERB FILEOS VOS_NT @@ -23,13 +17,13 @@ FILETYPE VFT_DLL { BLOCK "040904B0" { - VALUE "Comments", "http://ansicon.adoxa.cjb.net/" + VALUE "Comments", "http://ansicon.adoxa.vze.com/" VALUE "CompanyName", "Jason Hood" VALUE "FileDescription", "ANSI Console" VALUE "FileVersion", PVERSA VALUE "InternalName", "ANSI" BITS VALUE "LegalCopyright", "Freeware" - VALUE "OriginalFilename", "ANSI" BITS ".dll" + VALUE "OriginalFilename", ANSIDLL VALUE "ProductName", "ANSICON" VALUE "ProductVersion", PVERSA } diff --git a/ansicon.c b/ansicon.c index 4725ac1..ccdfeca 100644 --- a/ansicon.c +++ b/ansicon.c @@ -69,9 +69,13 @@ set the code page to convert strings correctly; expand wildcards for -t; write the date if appending to the log. + + v1.62, 18 July, 2013: + write the bits to the log; + test if creating the registry key fails (HKLM requires admin privileges). */ -#define PDATE L"14 February, 2013" +#define PDATE L"18 July, 2013" #include "ansicon.h" #include "version.h" @@ -85,13 +89,6 @@ int _CRT_glob = 0; #endif -#ifdef _WIN64 -# define BITS L"64" -#else -# define BITS L"32" -#endif - - #define CMDKEY L"Software\\Microsoft\\Command Processor" #define AUTORUN L"AutoRun" @@ -113,6 +110,7 @@ BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR ); // The DLL shares this variable, so injection requires it here. #ifdef _WIN64 DWORD LLW32; +extern LPVOID base; #endif @@ -239,7 +237,7 @@ int main( void ) if (installed) { fputws( L"\33[m", stdout ); - FreeLibrary( GetModuleHandle( L"ANSI" BITS L".dll" ) ); + FreeLibrary( GetModuleHandle( ANSIDLL ) ); } shell = run = TRUE; @@ -277,6 +275,34 @@ int main( void ) pi.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId); pi.hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, pi.dwThreadId ); SuspendThread( pi.hThread ); +#ifdef _WIN64 + // Find the base address of kernel32.dll if the 64-bit version is + // injecting into a 32-bit parent. + if (IsWow64Process( pi.hProcess, &gui ) && gui) + { + HANDLE hSnap; + MODULEENTRY32 me; + BOOL fOk; + + hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | + TH32CS_SNAPMODULE32, + pi.dwProcessId ); + if (hSnap != INVALID_HANDLE_VALUE) + { + me.dwSize = sizeof(MODULEENTRY32); + for (fOk = Module32First( hSnap, &me ); fOk; + fOk = Module32Next( hSnap, &me )) + { + if (_wcsicmp( me.szModule, L"kernel32.dll" ) == 0) + { + base = me.modBaseAddr; + break; + } + } + CloseHandle( hSnap ); + } + } +#endif if (!Inject( &pi, &gui, arg )) rc = 1; ResumeThread( pi.hThread ); @@ -366,10 +392,10 @@ arg_out: } else if (*arg) { - ansi = LoadLibrary( L"ANSI" BITS L".dll" ); + ansi = LoadLibrary( ANSIDLL ); if (ansi == NULL) { - print_error( L"ANSI" BITS L".dll" ); + print_error( ANSIDLL ); rc = 1; } @@ -511,10 +537,16 @@ void process_autorun( TCHAR cmd ) logstr, prog_path ) + 1); inst = (towlower( cmd ) == 'i'); - RegCreateKeyEx( (iswlower( cmd )) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, - CMDKEY, 0, NULL, - REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, - &cmdkey, &exist ); + if (RegCreateKeyEx( (iswlower(cmd)) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, + CMDKEY, 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, + &cmdkey, &exist ) != ERROR_SUCCESS) + { + fputws( L"ANSICON: could not update AutoRun", stderr ); + if (iswupper( cmd )) + fwprintf( stderr, L" (perhaps use -%c, or run as admin)", towlower(cmd) ); + fputws( L".\n", stderr ); + } exist = 0; RegQueryValueEx( cmdkey, AUTORUN, NULL, NULL, NULL, &exist ); if (exist == 0) @@ -766,7 +798,7 @@ void help( void ) _putws( L"ANSICON by Jason Hood .\n" L"Version " PVERS L" (" PDATE L"). Freeware.\n" -L"http://ansicon.adoxa.cjb.net/\n" +L"http://ansicon.adoxa.vze.com/\n" L"\n" #ifdef _WIN64 L"Process ANSI escape sequences in Windows console programs.\n" diff --git a/ansicon.rc b/ansicon.rc index 09b03c1..94aa66f 100644 --- a/ansicon.rc +++ b/ansicon.rc @@ -7,7 +7,7 @@ #include #include "version.h" -1 VERSIONINFO +VS_VERSION_INFO VERSIONINFO FILEVERSION PVERB PRODUCTVERSION PVERB FILEOS VOS_NT @@ -17,7 +17,7 @@ FILETYPE VFT_APP { BLOCK "040904B0" { - VALUE "Comments", "http://ansicon.adoxa.cjb.net/" + VALUE "Comments", "http://ansicon.adoxa.vze.com/" VALUE "CompanyName", "Jason Hood" VALUE "FileDescription", "ANSI Console" VALUE "FileVersion", PVERSA @@ -34,3 +34,21 @@ FILETYPE VFT_APP VALUE "Translation", 0x0409, 0x04B0 } } + +// Add a manifest for the 32-bit version, to prevent registry redirection when +// trying to use HKLM. +#ifndef _WIN64 +1 24 +{ +"\ +\ +\ + \ + \ + \ + \ + \ +\ +" +} +#endif diff --git a/injdll32.c b/injdll32.c index 738b742..9b0b598 100644 --- a/injdll32.c +++ b/injdll32.c @@ -32,17 +32,84 @@ TWow64SetThreadContext Wow64SetThreadContext; #define GetThreadContext Wow64GetThreadContext #define SetThreadContext Wow64SetThreadContext -extern -#endif +#define MakeVA( cast, offset ) (cast)((DWORD_PTR)base + (DWORD)(offset)) + +extern DWORD LLW32; +LPVOID base; + +int export_cmp( const void* a, const void* b ) +{ + return strcmp( (LPCSTR)a, MakeVA( LPCSTR, *(const PDWORD)b ) ); +} + + +/* + Get the relative address of the 32-bit LoadLibraryW function from 64-bit code. + This was originally done via executing a helper program (ANSI-LLW.exe), but I + never liked doing that, so now I do it the "hard" way - load the 32-bit + kernel32.dll directly and search the exports. +*/ +BOOL get_LLW32( void ) +{ + HMODULE kernel32; + TCHAR buf[MAX_PATH]; + UINT len; + PIMAGE_DOS_HEADER pDosHeader; + PIMAGE_NT_HEADERS32 pNTHeader; + PIMAGE_EXPORT_DIRECTORY pExportDir; + PDWORD fun_table, name_table; + PWORD ord_table; + PDWORD pLLW; + + len = GetSystemWow64Directory( buf, MAX_PATH ); + wcscpy( buf + len, L"\\kernel32.dll" ); + // MinGW-w64 has a typo, calling it LINRARY. + kernel32 = LoadLibraryEx( buf, NULL, 0x20/*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/ ); + if (kernel32 == NULL) + { + DEBUGSTR( 1, L"Unable to load 32-bit kernel32.dll!" ); + return FALSE; + } + // The handle uses low bits as flags, so strip 'em off. + base = (LPVOID)((DWORD_PTR)kernel32 & ~0xFFFF); + + pDosHeader = (PIMAGE_DOS_HEADER)base; + pNTHeader = MakeVA( PIMAGE_NT_HEADERS32, pDosHeader->e_lfanew ); + pExportDir = MakeVA( PIMAGE_EXPORT_DIRECTORY, + pNTHeader->OptionalHeader. + DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]. + VirtualAddress ); + + fun_table = MakeVA( PDWORD, pExportDir->AddressOfFunctions ); + name_table = MakeVA( PDWORD, pExportDir->AddressOfNames ); + ord_table = MakeVA( PWORD, pExportDir->AddressOfNameOrdinals ); + + pLLW = bsearch( "LoadLibraryW", name_table, pExportDir->NumberOfNames, + sizeof(DWORD), export_cmp ); + if (pLLW == NULL) + { + DEBUGSTR( 1, L"Could not find LoadLibraryW!" ); + FreeLibrary( kernel32 ); + return FALSE; + } + LLW32 = fun_table[ord_table[pLLW - name_table]]; + + FreeLibrary( kernel32 ); + return TRUE; +} +#else DWORD LLW32; +#endif void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll ) { CONTEXT context; + DWORD ep; DWORD len; LPVOID mem; DWORD mem32; + DWORD pr; #define CODESIZE 20 BYTE code[CODESIZE+TSIZE(MAX_PATH)]; union @@ -50,6 +117,9 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll ) PBYTE pB; PDWORD pL; } ip; +#ifdef _WIN64 + BOOL entry = FALSE; +#endif #ifdef IMPORT_WOW64 if (Wow64GetThreadContext == 0) @@ -71,46 +141,105 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll ) if (len > TSIZE(MAX_PATH)) return; - if (LLW32 == 0) - { -#ifdef _WIN64 - STARTUPINFO si; - PROCESS_INFORMATION pi; - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - // ...ANSI32.dll\0 - CopyMemory( code, dll, len - TSIZE(7) ); - // ...ANSI-LLW.exe\0 - CopyMemory( code + len - TSIZE(7), L"-LLW.exe", TSIZE(9) ); - if (!CreateProcess( (LPCTSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL, - &si, &pi )) - { - DEBUGSTR( 1, L"Failed to execute \"%s\".", (LPCTSTR)code ); - return; - } - WaitForSingleObject( pi.hProcess, INFINITE ); - GetExitCodeProcess( pi.hProcess, &LLW32 ); - CloseHandle( pi.hProcess ); - CloseHandle( pi.hThread ); -#else - LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ), - "LoadLibraryW" ); -#endif - } - CopyMemory( code + CODESIZE, dll, len ); len += CODESIZE; - context.ContextFlags = CONTEXT_CONTROL; + context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; GetThreadContext( ppi->hThread, &context ); mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT, - PAGE_EXECUTE_READWRITE ); + PAGE_READWRITE ); mem32 = (DWORD)(DWORD_PTR)mem; ip.pB = code; - *ip.pB++ = 0x68; // push eip - *ip.pL++ = context.Eip; + ep = context.Eip; + if (LLW32 == 0) + { +#ifndef _WIN64 + LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ), + "LoadLibraryW" ); +#else + struct unicode_string + { + USHORT Length; + USHORT MaximumLength; + DWORD Buffer; + }; + struct ldr_module // incomplete definition + { + DWORD next, prev; + DWORD baseAddress; + DWORD entryPoint; + DWORD sizeOfImage; + struct unicode_string fullDllName; + struct unicode_string baseDllName; + } ldr; + WCHAR basename[MAX_PATH]; + + if (!get_LLW32()) + return; + // Determine the base address of the 32-bit kernel32.dll. If injecting + // into the parent process, base has already been determined. Otherwise, + // use the PEB to walk the loaded modules. + if (base == 0) + { + // When a process is created suspended, EAX has the entry point and EBX + // points to the PEB. + if (!ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ), + ip.pL, 4, NULL )) + { + DEBUGSTR( 1, L"Failed to read Ldr from PEB." ); + return; + } + // In case we're a bit slow (which seems to be unlikely), set up an + // infinite loop as the entry point. + WriteProcessMemory( ppi->hProcess, mem, "\xEB\xFE", 2, NULL ); + FlushInstructionCache( ppi->hProcess, mem, 2 ); + ep = context.Eax; + context.Eax = mem32; + SetThreadContext( ppi->hThread, &context ); + VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr ); + // Now resume the thread, as the PEB hasn't even been created yet. + ResumeThread( ppi->hThread ); + while (*ip.pL == 0) + { + Sleep( 0 ); + ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ), + ip.pL, 4, NULL ); + } + // Read PEB_LDR_DATA.InInitializationOrderModuleList.Flink. + ReadProcessMemory( ppi->hProcess, UIntToPtr( *ip.pL + 0x1c ), + &ip.pL[1], 4, NULL ); + // Sometimes we're so quick ntdll.dll is the only one present, so keep + // looping until kernel32.dll shows up. + for (;;) + { + ldr.next = ip.pL[1]; + do + { + ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.next ), + &ldr, sizeof(ldr), NULL ); + ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.baseDllName.Buffer ), + basename, ldr.baseDllName.MaximumLength, NULL ); + if (_wcsicmp( basename, L"kernel32.dll" ) == 0) + { + LLW32 += ldr.baseAddress; + goto gotit; + } + } while (ldr.next != *ip.pL + 0x1c); + } + gotit: + SuspendThread( ppi->hThread ); + VirtualProtectEx( ppi->hProcess, mem, len, pr, &pr ); + entry = TRUE; + } + else + LLW32 += PtrToUint( base ); +#endif + } + + *ip.pB++ = 0x68; // push ep + *ip.pL++ = ep; *ip.pB++ = 0x9c; // pushf *ip.pB++ = 0x60; // pusha *ip.pB++ = 0x68; // push L"path\to\ANSI32.dll" @@ -123,6 +252,11 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll ) WriteProcessMemory( ppi->hProcess, mem, code, len, NULL ); FlushInstructionCache( ppi->hProcess, mem, len ); + VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr ); +#ifdef _WIN64 + if (entry) + return; +#endif context.Eip = mem32; SetThreadContext( ppi->hThread, &context ); } diff --git a/makefile b/makefile deleted file mode 100644 index e9c4309..0000000 --- a/makefile +++ /dev/null @@ -1,85 +0,0 @@ -# Makefile for ANSICON. -# Jason Hood, 11 March, 2006. Updated 20 June, 2009. - -# I've used TDM64 (gcc 4.6.1), building the 32-bit version in the x86 directory -# and the 64-bit version in the x64 directory. MinGW32 (gcc 3.4.5) will also -# build the 32-bit version. - -# 19 November, 2010: -# explicitly use 64-bit flags, in case the compiler isn't. -# -# 13 December, 2011: -# use CMD for file operations, not programs from fileutils. -# -# 23 November, 2012: -# set the base address of the DLLs to AC0000[00] (AnsiCon). - -CC = gcc -CFLAGS = -O2 -Wall - -X86OBJS = x86/proctype.o x86/injdll32.o x86/util.o -X64OBJS = x64/proctype.o x64/injdll64.o x64/injdll32.o x64/util.o - -x86/%.o: %.c ansicon.h - $(CC) -m32 -c $(CFLAGS) $< -o $@ - -x86/%v.o: %.rc version.h - windres -U _WIN64 -F pe-i386 $< $@ - -x64/%.o: %.c ansicon.h - $(CC) -m64 -c $(CFLAGS) $< -o $@ - -x64/%v.o: %.rc version.h - windres -F pe-x86-64 $< $@ - -all: ansicon32 ansicon64 - -ansicon32: x86 x86/ansicon.exe x86/ANSI32.dll - -ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll x64/ANSI-LLW.exe - -x86: - cmd /c "mkdir x86" - -x86/ansicon.exe: x86/ansicon.o $(X86OBJS) x86/ansiconv.o - $(CC) -m32 $+ -s -o $@ - -x86/ANSI32.dll: x86/ANSI.o $(X86OBJS) x86/ansiv.o - $(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000 - -x64: - cmd /c "mkdir x64" - -x64/ansicon.exe: x64/ansicon.o $(X64OBJS) x64/ansiconv.o - $(CC) -m64 $+ -s -o $@ - -x64/ANSI64.dll: x64/ANSI.o $(X64OBJS) x64/ansiv.o - $(CC) -m64 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC000000 - -x64/ANSI32.dll: x64/ANSI32.o x64/proctype32.o x86/injdll32.o x86/util.o x86/ansiv.o - $(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000 - -x64/ANSI-LLW.exe: ANSI-LLW.c - $(CC) -m32 $(CFLAGS) $< -s -o $@ - -x86/ansicon.o: version.h -x86/ANSI.o: version.h -x64/ansicon.o: version.h -x64/ANSI.o: version.h -x86/util.o: version.h -x64/util.o: version.h -x86/ansiconv.o: ansicon.rc -x86/ansiv.o: ansi.rc -x64/ansiconv.o: ansicon.rc -x64/ansiv.o: ansi.rc - -x64/ANSI32.o: ANSI.c - $(CC) -m32 -DW32ON64 $(CFLAGS) $< -c -o $@ -x64/proctype32.o: proctype.c - $(CC) -m32 -DW32ON64 $(CFLAGS) $< -c -o $@ - -# Need two commands, because if the directory doesn't exist, it won't delete -# anything at all. -clean: - -cmd /c "del x86\*.o 2>nul" - -cmd /c "del x64\*.o 2>nul" diff --git a/makefile.gcc b/makefile.gcc new file mode 100644 index 0000000..fab4f3c --- /dev/null +++ b/makefile.gcc @@ -0,0 +1,112 @@ +# MinGW/MinGW-w64 makefile for ANSICON. +# Jason Hood, 11 March, 2006. Updated 20 June, 2009. +# +# 19 November, 2010: +# explicitly use 64-bit flags, in case the compiler isn't. +# +# 13 December, 2011: +# use CMD for file operations, not programs from fileutils. +# +# 23 November, 2012: +# set the base address of the DLLs to AC0000[00] (AnsiCon). +# +# 17 & 18 July, 2013: +# work with 32-bit only, 64-bit only or multilib compilers; +# hide the commands (use V=1 to show them). +# +# Tested with: +# * MinGW/gcc 4.7.2; +# * tdm-gcc-4.7.1-2; +# * tdm64-gcc-4.7.1-3; +# * MinGW-builds x64-4.8.1-release-posix-seh-rev1. + +CC = gcc +CFLAGS = -O2 -Wall + +#ARCH = 32 +#ARCH = 64 +#ARCH = multi + +ifndef ARCH +# Use the machine to distinguish between MinGW and MinGW-w64. +ifeq (,$(findstring 64,$(shell gcc -dumpmachine))) +ARCH = 32 +else +# It's 64-bit, if it's multi the lib name will be different. +ifeq ($(shell gcc -m32 -print-libgcc-file-name),$(shell gcc -m64 -print-libgcc-file-name)) +ARCH = 64 +else +ARCH = multi +endif +endif +endif + +X86OBJS = x86/proctype.o x86/injdll32.o x86/util.o +X64OBJS = x64/proctype.o x64/injdll64.o x64/injdll32.o x64/util.o + +V ?= 0 +ifeq ($(V),0) +CCmsg = @echo $<; +RCmsg = $(CCmsg) +LDmsg = @echo $@; +endif + +x86/%.o: %.c ansicon.h + $(CCmsg)$(CC) -m32 -c $(CFLAGS) $< -o $@ + +x86/%v.o: %.rc version.h + $(RCmsg)windres -U _WIN64 -F pe-i386 $< $@ + +x64/%.o: %.c ansicon.h + $(CCmsg) $(CC) -m64 -c $(CFLAGS) $< -o $@ + +x64/%v.o: %.rc version.h + $(RCmsg)windres -F pe-x86-64 $< $@ + +x64/%32.o: %.c + $(CCmsg)$(CC) -m32 -DW32ON64 $(CFLAGS) $< -c -o $@ + + +ifeq ($(ARCH),multi) +all: ansicon32 ansicon64 +else +all: ansicon$(ARCH) +endif + +ansicon32: x86 x86/ansicon.exe x86/ANSI32.dll x64 x64/ANSI32.dll + +ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll + +x86: + cmd /c "mkdir x86" + +x86/ansicon.exe: x86/ansicon.o $(X86OBJS) x86/ansiconv.o + $(LDmsg)$(CC) -m32 $+ -s -o $@ + +x86/ANSI32.dll: x86/ANSI.o $(X86OBJS) x86/ansiv.o + $(LDmsg)$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000 + +x64: + cmd /c "mkdir x64" + +x64/ansicon.exe: x64/ansicon.o $(X64OBJS) x64/ansiconv.o + $(LDmsg)$(CC) -m64 $+ -s -o $@ + +x64/ANSI64.dll: x64/ANSI.o $(X64OBJS) x64/ansiv.o + $(LDmsg)$(CC) -m64 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC000000 + +x64/ANSI32.dll: x64/ANSI32.o x64/proctype32.o x86/injdll32.o x86/util.o x86/ansiv.o + $(LDmsg)$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000 + +x86/ansicon.o: version.h +x86/ANSI.o: version.h +x86/util.o: version.h +x64/ansicon.o: version.h +x64/ANSI.o: version.h +x64/util.o: version.h + +# Need two commands, because if the directory doesn't exist, it won't delete +# anything at all. +clean: + -cmd /c "del x86\*.o 2>nul" + -cmd /c "del x64\*.o 2>nul" diff --git a/makefile.vc b/makefile.vc index 5e51425..96937b2 100644 --- a/makefile.vc +++ b/makefile.vc @@ -1,17 +1,23 @@ # VC makefile for ANSICON. # Jason Hood, 15 November, 2010. - -# I've used Visual C++ 2008 Express for the 32-bit version and the 2003 R2 -# Platform SDK for the 64-bit version. Since these are entirely separate -# environments, define BITS to decide which should be built. Note that the -# 64-bit version still requires the 32-bit ANSI32.dll, so both environments -# are required and you should build the 32-bit version before the 64-bit. - +# +# Tested with: +# * Visual Studio 6.0 (VC6); +# * Visual C++ 2003 Toolkit (VC7); +# * Platform SDK for Windows Server 2003 R2 (VC8 64-bit); +# * Visual Studio 2008 Express SP1 (VC9); +# * Visual Studio 2010 Professional (VC10). +# +# Note that the 64-bit version still requires a 32-bit compiler. +# # 22 & 23 November, 2012: # determine if the PSDK is used automatically; # use AC0000[00] (AnsiCon) as the base address; # twiddle stuff around to support VC6 (with 2003 PSDK) for the 32-bit version; # determine BITS automatically. +# +# 18 July, 2013: +# hide the commands (use V=1 to show them). #BITS = 32 #BITS = 64 @@ -29,6 +35,7 @@ DIR = x86 !ELSE !IF $(BITS) == 64 DIR = x64 +RFLAGS = /D_WIN64 !ELSE !ERROR BITS should be defined to 32 or 64. !ENDIF @@ -36,9 +43,10 @@ DIR = x64 # This is required for the 2003 Platform SDK, but not for Visual Studio 2010. !IF "$(_NMAKE_VER)" == "7.00.8882" +!IF $(BITS) == 64 LIBS64 = bufferoverflowu.lib -# The 2003 Toolkit doesn't have MSVCRT.LIB (but VC98 does). -!IF $(BITS) == 32 && !DEFINED(SHARE) && !DEFINED(MSVCDIR) +# The 2003 Toolkit doesn't have MSVCRT.LIB, but VC98 does. +!ELSEIF !DEFINED(SHARE) && !DEFINED(MSVCDIR) SHARE = !ENDIF !ENDIF @@ -48,22 +56,34 @@ SHARE = SHARE = /MD !ENDIF -CC = cl -CFLAGS = /nologo /W3 /Ox /GF $(SHARE) /D_CRT_SECURE_NO_WARNINGS -LIBS = advapi32.lib user32.lib +# Manifest tool to embed the manifest required by 2008. +MT = mt.exe + +CFLAGS = /nologo /W3 /O2 $(SHARE) /D_CRT_SECURE_NO_WARNINGS +LIBS = advapi32.lib user32.lib $(LIBS64) X86OBJS = x86\proctype.obj x86\injdll32.obj x86\util.obj X64OBJS = x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\util.obj +!IF !DEFINED(V) +V = 0 +!ENDIF +!IF $(V) == 0 +CCmsg = @ +RCmsg = @echo $<& +LDmsg = @echo $@& +MTmsg = @echo Embedding manifest& +!ENDIF + {}.c{$(DIR)}.obj: - $(CC) /c $(CFLAGS) /Fo$@ $< + $(CCmsg)$(CC) /c $(CFLAGS) /Fo$@ $< {}.rc{$(DIR)}.res: - rc /fo$@ $< + $(RCmsg)$(RC) $(RFLAGS) /fo$@ $< all: ansicon$(BITS) -ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64 x64\ANSI32.dll x64\ANSI-LLW.exe +ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64 x64\ANSI32.dll ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll @@ -71,25 +91,34 @@ x86: mkdir x86 x86\ansicon.exe: x86\ansicon.obj $(X86OBJS) x86\ansicon.res - $(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) /link /filealign:512 + $(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) /link /filealign:512 +!IF "$(_NMAKE_VER)" == "9.00.30729.01" + $(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;1 + @del $@.manifest +!ENDIF x86\ANSI32.dll: x86\ANSI.obj $(X86OBJS) x86\ansi.res - $(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512 + $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512 +!IF "$(_NMAKE_VER)" == "9.00.30729.01" + $(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;2 + @del $@.manifest +!ENDIF x64: mkdir x64 x64\ansicon.exe: x64\ansicon.obj $(X64OBJS) x64\ansicon.res - $(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) $(LIBS64) + $(LDmsg)$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res - $(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) $(LIBS64) /link /base:0xAC000000 /section:.shared,s + $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC000000 /section:.shared,s x64\ANSI32.dll: x64\ANSI32.obj x64\proctype32.obj x86\injdll32.obj x86\util.obj x86\ansi.res - $(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512 - -x64\ANSI-LLW.exe: ANSI-LLW.c - $(CC) $(CFLAGS) /Fe$@ /Fo$*.obj $? $(LIBS64) + $(LDmsg)$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512 +!IF "$(_NMAKE_VER)" == "9.00.30729.01" + $(MTmsg)$(MT) /nologo -manifest $@.manifest -outputresource:$@;2 + @del $@.manifest +!ENDIF ansicon.c: ansicon.h version.h ansicon.rc: version.h @@ -101,9 +130,9 @@ injdll64.c: ansicon.h proctype.c: ansicon.h x64\ANSI32.obj: ANSI.c - $(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $? + $(CCmsg)$(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $? x64\proctype32.obj: proctype.c - $(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $? + $(CCmsg)$(CC) /DW32ON64 /c $(CFLAGS) /Fo$@ $? clean: -del $(DIR)\*.obj $(DIR)\*.res $(DIR)\*.lib $(DIR)\*.exp diff --git a/readme.txt b/readme.txt index 17c2d98..e387721 100644 --- a/readme.txt +++ b/readme.txt @@ -1,65 +1,62 @@ ANSICON - Copyright 2005-2012 Jason Hood + Copyright 2005-2013 Jason Hood - Version 1.61. Freeware + Version 1.62. Freeware - =========== - Description - =========== +Description +=========== ANSICON provides ANSI escape sequences for Windows console programs. It - provides much the same functionality as `ANSI.SYS' does for MS-DOS. + provides much the same functionality as 'ANSI.SYS' does for MS-DOS. - ============ - Requirements - ============ +Requirements +============ 32-bit: Windows 2000 Professional and later (it won't work with NT or 9X). 64-bit: Vista and later (it won't work with XP64). - ============ - Installation - ============ +Installation +============ - Add x86 (if your OS is 32-bit) or x64 (if 64-bit) to your PATH, or copy - the relevant files to a directory already on the PATH. Alternatively, - use option `-i' (or `-I') to install it permanently, by adding an entry - to CMD.EXE's AutoRun registry value (current user or local machine, - respectively). Uninstall simply involves closing any programs that are - currently using it, running with `-u' (and/or `-U') to remove the Auto- - Run entry/ies, then removing the directory from PATH or deleting the - files. No other changes are made. + Add "x86" (if your OS is 32-bit) or "x64" (if 64-bit) to your PATH, or copy + the relevant files to a directory already on the PATH. Alternatively, use + option '-i' (or '-I', if permitted) to install it permanently, by adding an + entry to CMD.EXE's AutoRun registry value (current user or local machine, + respectively). - --------- - Upgrading - --------- + Uninstall simply involves closing any programs that are currently using it; + running with '-u' (and/or '-U') to remove it from AutoRun; removing the + directory from PATH; and deleting the files. No other changes are made + (although you may have also created environment variables). + +Upgrading +--------- Delete ANSI.dll, it has been replaced with ANSI32.dll. - Delete ANSI-LLA.exe, it has been replaced with ANSI-LLW.exe. + Delete ANSI-LLA.exe and ANSI-LLW.exe, they are no longer used. Uninstall a pre-1.50 version and reinstall with this version. - ===== - Usage - ===== +Usage +===== Options (case sensitive): - -l Log to %temp%\ansicon.log. + -l Log to "%TEMP%\ansicon.log". - -p Enable the parent process (i.e. the command shell used to - run ANSICON) to recognise escapes. + -p Enable the parent process (i.e. the command shell used to run + ANSICON) to recognise escapes. -m Set the current (and default) attribute to grey on black - ("monochrome"), or the attribute following the `m' (please - use `COLOR /?' for attribute values). + ("monochrome"), or the attribute following the 'm' (please + use 'COLOR /?' for attribute values). - -e Echo the command line - a space or tab after the `e' is + -e Echo the command line - a space or tab after the 'e' is ignored, the remainder is displayed verbatim. -E As above, but no newline is added. @@ -70,22 +67,22 @@ -T Display "==> FILE NAME <==", a blank line (or an error message), the file and another blank line. - Running ANSICON with no arguments will start a new instance of the com- - mand processor (the program defined by the `ComSpec' environment var- - iable, typically `CMD.EXE'), or display standard input if it is redir- - ected. Any argument will be treated as a program and its arguments. + Running ANSICON with no arguments will start a new instance of the command + processor (the program defined by the 'ComSpec' environment variable, typ- + ically 'CMD.EXE'), or display standard input if it is redirected. Any arg- + ument will be treated as a program and its arguments. - Eg: `ansicon -m30 -t file.ans' will display `file.ans' using black on + E.g.: 'ansicon -m30 -t file.ans' will display "file.ans" using black on cyan as the default color. - The attribute may start with "-" to permanently reverse the foreground - and background colors (but not when using `-p'). Eg: `ansicon -m-f0 -t + The attribute may start with '-' to permanently reverse the foreground and + background colors (but not when using '-p'). E.g.: 'ansicon -m-f0 -t file.log' will use reversed black on white as the default (i.e. white on black, with foreground sequences changing the background). - If you experience trouble with certain programs, the log may help in - finding the cause; it can be found at "%TEMP%\ansicon.log". A number - should follow the `l': + If you experience trouble with certain programs, the log may help in find- + ing the cause; it can be found at "%TEMP%\ansicon.log". A number should + follow the 'l': 0 No logging 1 Log process start and end @@ -95,53 +92,55 @@ 8 Append to the existing file (add to any of the above) 16 Log all imported modules (add to any of the above) - The log option will not work with `-p'; set the environment variable - ANSICON_LOG instead. The variable is only read once when a new process - is started; changing it won't affect running processes. If you identify - a module that causes problems, add it to the ANSICON_EXC environment - variable (see ANSICON_API below, but the extension is required). + The log option will not work with '-p'; set the environment variable + ANSICON_LOG instead. The variable is only read once when a new process is + started; changing it won't affect running processes. If you identify a + module that causes problems, add it to the ANSICON_EXC environment variable + (see ANSICON_API below, but the extension is required). + + E.g.: 'ansicon -l5' will start a new command processor, logging every pro- + cess it starts along with their output. Once installed, the ANSICON environment variable will be created. This - variable is of the form "WxH (wxh)", where W & H are the width and - height of the buffer and w & h are the width and height of the window. - The variable is updated whenever a program reads it directly (i.e. as - an individual request, not as part of the entire environment block). - For example, "set an" will not update it, but "echo %ansicon%" will. - Also created is ANSICON_VER, which contains the version without the - point (1.50 becomes "150"). This variable does not exist as part of the - environment block ("set an" will not show it). + variable is of the form "WxH (wxh)", where 'W' & 'H' are the width and + height of the buffer and 'w' & 'h' are the width and height of the window. + The variable is updated whenever a program reads it directly (i.e. as an + individual request, not as part of the entire environment block). For + example, 'set an' will not update it, but 'echo %ansicon%' will. Also + created is ANSICON_VER, which contains the version without the point (1.50 + becomes "150"). This variable does not exist as part of the environment + block ('set an' will not show it). If installed, GUI programs will not be hooked. Either start the program - directly with `ansicon', or add it to the ANSICON_GUI variable (see + directly with 'ansicon', or add it to the ANSICON_GUI variable (see ANSICON_API below). - Using `ansicon' after install will always start with the default attrib- - utes, restoring the originals on exit; all other programs will use the - current attributes. The shift state is always reset for a new process. + Using 'ansicon' after install will always start with the default attrib- + utes, restoring the originals on exit; all other programs will use the cur- + rent attributes. The shift state is always reset for a new process. - The Windows API WriteFile and WriteConsoleA functions will set the num- - ber of characters written, not the number of bytes. When using a multi- - byte character set, this results in a smaller number (since multiple - bytes are used to represent a single character). Some programs recog- - nise this as a reduced write and will inadvertently repeat previous - characters. If you discover such a program, use the ANSICON_API envir- - onment variable to record it and override the API, returning the origin- - al byte count. Ruby is an example of such a program (at least, up till - 1.9.2p0), so use "set ANSICON_API=ruby" to avoid the repitition. The - full syntax of the variable is: + The Windows API WriteFile and WriteConsoleA functions will set the number + of characters written, not the number of bytes. When using a multibyte + character set, this results in a smaller number (since multiple bytes are + used to represent a single character). Some programs recognise this as a + reduced write and will inadvertently repeat previous characters. If you + discover such a program, use the ANSICON_API environment variable to record + it and override the API, returning the original byte count. Ruby (prior to + 1.9.3) is an example of such a program, so use 'set ANSICON_API=ruby' to + avoid the repitition. The full syntax is: ANSICON_API=[!]program;program;program... - PROGRAM is the name of the program, with no path and extension. The - leading exclamation inverts the usage, meaning the API will always be - overridden, unless the program is in the list. The variable can be made - permanent by going to System Properties, selecting the Advanced tab and - clicking Environment Variables (using XP; Vista/7 may be different). + PROGRAM is the name of the program, with no path and extension. The lead- + ing exclamation inverts the usage, meaning the API will always be over- + ridden, unless the program is in the list. The variable can be made perm- + anent by going to System Properties, selecting the Advanced tab (with Vista + onwards, this can be done by running "SystemPropertiesAdvanced") and click- + ing Environment Variables. - ==================== - Sequences Recognised - ==================== +Sequences Recognised +==================== The following escape sequences are recognised. @@ -178,40 +177,36 @@ \e[#k VPB Line Position Backward \e[#e VPR Line Position Forward - `\e' represents the escape character (ASCII 27); `#' represents a - decimal number (optional, in most cases defaulting to 1); BEL, SO and - SI are ASCII 7, 14 and 15. Regarding SGR: bold will set the foreground - intensity; underline and blink will set the background intensity; - conceal uses background as foreground. See `sequences.txt' for a more - complete description. + '\e' represents the escape character (ASCII 27); '#' represents a decimal + number (optional, in most cases defaulting to 1); BEL, SO and SI are ASCII + 7, 14 and 15. Regarding SGR: bold will set the foreground intensity; blink + and underline will set the background intensity; conceal uses background as + foreground. See "sequences.txt" for a more complete description. - I make a distinction between "\e[m" and "\e[0;...m". Both will restore - the original foreground/background colors (and so "0" should be the - first parameter); the former will also restore the original bold and - underline attributes, whilst the latter will explicitly reset them. The - environment variable ANSICON_DEF can be used to change the default col- - ors (same value as `-m'; setting the variable does not change the cur- - rent colors). + I make a distinction between '\e[m' and '\e[0;...m'. Both will restore the + original foreground/background colors (and so '0' should be the first para- + meter); the former will also restore the original bold and underline attri- + butes, whilst the latter will explicitly reset them. The environment var- + iable ANSICON_DEF can be used to change the default colors (same value as + '-m'; setting the variable does not change the current colors). - ================= - Sequences Ignored - ================= +Sequences Ignored +================= The following escape sequences are explicitly ignored. - \e(? Designate G0 character set (`?' is anything). - \e)? Designate G1 character set (`?' is anything). + \e(? Designate G0 character set ('?' is anything). + \e)? Designate G1 character set ('?' is anything). \e[?... Private sequence \e[>... Private sequence - The G0 character set is always ASCII; the G1 character set is always - the DEC Special Graphics Character Set. + The G0 character set is always ASCII; the G1 character set is always the + DEC Special Graphics Character Set. - ================================== - DEC Special Graphics Character Set - ================================== +DEC Special Graphics Character Set +================================== This is my interpretation of the set, as shown by http://vt100.net/docs/vt220-rm/table2-4.html. @@ -252,34 +247,34 @@ } U+00A3 Pound Sign ~ U+00B7 Middle Dot - G1.txt is a Unicode file to view the glyphs "externally". G1.bat is a - batch file (using `x86\ansicon') to show the glyphs in the console. The + batch file (using 'x86\ansicon') to show the glyphs in the console. The characters will appear as they should using Lucida (other than the Sym- - bols), but code page will influence them when using a raster font (but - of particular interest, 437 and 850 both show the Box Drawings). + bols), but code page will influence them when using a raster font (but of + particular interest, 437 and 850 both show the Box Drawings). - =========== - Limitations - =========== +Limitations +=========== The entire console buffer is used, not just the visible window. - Building rubyinstaller on Win7 crashes (XP is fine). + There's a conflict with NVIDIA's drivers, requiring the setting of the + Environment Variable: - There's a conflict with NVIDIA's 64-bit drivers, requiring the setting - of the Environment Variable: - - ANSICON_EXC=nvd3d9wrap.dll,nvd3d9wrapx.dll + ANSICON_EXC=nvd3d9wrap.dll;nvd3d9wrapx.dll - =============== - Version History - =============== +Version History +=============== Legend: + added, - bug-fixed, * changed. + 1.62 - 18 July, 2013: + - indicate if opening HKLM failed; + * removed ANSI-LLW.exe again, properly this time; + * add the architecture (32- or 64-bit) to the log. + 1.61 - 14 February, 2013: * revert back to using ANSI-LLW.exe, as the new method was unreliable. @@ -311,7 +306,7 @@ - -p by itself will not restore original color; - output error messages to stderr; * logging is always available, with various levels; include the pid; - * don't automatically hook GUI programs, use `ansicon' or ANSICON_GUI; + * don't automatically hook GUI programs, use 'ansicon' or ANSICON_GUI; * always place first in AutoRun; don't run if already installed; + global reverse video capability; + added ANSICON_VER to provide version/install test; @@ -401,36 +396,34 @@ + initial release. - =============== - Acknowledgments - =============== +Acknowledgments +=============== - Jean-Louis Morel, for his Perl package Win32::Console::ANSI. It - provided the basis of `ANSI.dll'. + Jean-Louis Morel, for his Perl package Win32::Console::ANSI. It provided + the basis of 'ANSI.dll'. - Sergey Oblomov (hoopoepg), for Console Manager. It provided the basis - of `ansicon.exe'. + Sergey Oblomov (hoopoepg), for Console Manager. It provided the basis of + 'ansicon.exe'. - Anton Bassov's article "Process-wide API spying - an ultimate hack" in - "The Code Project". + Anton Bassov's article "Process-wide API spying - an ultimate hack" in "The + Code Project". - Richard Quadling - his persistence in finding bugs has made ANSICON - what it is today. + Richard Quadling - his persistence in finding bugs has made ANSICON what it + is today. - Dmitry Menshikov, Marko Bozikovic and Philippe Villiers, for their - assistance in making the 64-bit version a reality. + Dmitry Menshikov, Marko Bozikovic and Philippe Villiers, for their assis- + tance in making the 64-bit version a reality. Luis Lavena and the Ruby people for additional improvements. Leigh Hebblethwaite for documentation tweaks. - ======= - Contact - ======= +Contact +======= mailto:jadoxa@yahoo.com.au - http://ansicon.adoxa.cjb.net/ + http://ansicon.adoxa.vze.com/ https://github.com/adoxa/ansicon Jason Hood @@ -440,19 +433,17 @@ Australia - ============ - Distribution - ============ +Distribution +============ - The original zipfile can be freely distributed, by any means. However, - I would like to be informed if it is placed on a CD-ROM (other than an - archive compilation; permission is granted, I'd just like to know). - Modified versions may be distributed, provided it is indicated as such - in the version text and a source diff is made available. In particular, - the supplied binaries are freely redistributable, but the x64 binaries - must also include COPYING.MinGW-w64-runtime.txt. A formal license (zlib) - is available in LICENSE.txt. + The original zipfile can be freely distributed, by any means. However, I + would like to be informed if it is placed on a CD-ROM (other than an arch- + ive compilation; permission is granted, I'd just like to know). Modified + versions may be distributed, provided it is indicated as such in the ver- + sion text and a source diff is made available. In particular, the supplied + binaries are freely redistributable. A formal license (zlib) is available + in LICENSE.txt. - ============================== - Jason Hood, 14 February, 2013. +========================== +Jason Hood, 18 July, 2013. diff --git a/util.c b/util.c index a5ec64a..8bb4524 100644 --- a/util.c +++ b/util.c @@ -60,7 +60,7 @@ void DEBUGSTR( int level, LPTSTR szFormat, ... ) { SYSTEMTIME now; GetLocalTime( &now ); - fprintf( file, "ANSICON v" PVERSA " log (%d) started " + fprintf( file, "ANSICON (" BITSA "-bit) v" PVERSA " log (%d) started " "%d-%.2d-%.2d %d:%.2d:%.2d\n", log_level, now.wYear, now.wMonth, now.wDay, diff --git a/version.h b/version.h index a5dcde9..38c668e 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,18 @@ version.h - Version defines. */ -#define PVERS L"1.61" // wide string -#define PVERSA "1.61" // ANSI string (windres 2.16.91 didn't like L) -#define PVERE L"161" // wide environment string -#define PVEREA "161" // ANSI environment string -#define PVERB 1,6,1,0 // binary (resource) +#define PVERS L"1.62" // wide string +#define PVERSA "1.62" // ANSI string (windres 2.16.91 didn't like L) +#define PVERE L"162" // wide environment string +#define PVEREA "162" // ANSI environment string +#define PVERB 1,6,2,0 // binary (resource) + +#ifdef _WIN64 +# define BITS L"64" +# define BITSA "64" +#else +# define BITS L"32" +# define BITSA "32" +#endif + +#define ANSIDLL L"ANSI" BITS L".dll"