Initial commit (v1.30)

This commit is contained in:
Jason Hood 2010-11-08 15:31:01 +10:00
commit a551a6e6c8
18 changed files with 2712 additions and 0 deletions

17
ANSI-LLA.c Normal file
View File

@ -0,0 +1,17 @@
/*
ANSI-LLA.c - Output the 32-bit address of LoadLibraryA.
Jason Hood, 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.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int main( void )
{
return (DWORD)GetProcAddress( GetModuleHandleA( "kernel32.dll" ),
"LoadLibraryA" );
}

1306
ANSI.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,169 @@
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.
===============================================================
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
<http://lists.debian.org/debian-legal/2004/12/msg00295.html>, 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.

41
ansi.rc Normal file
View File

@ -0,0 +1,41 @@
/*
ansi.rc - Version resource for ANSI{32,64}.dll.
Jason Hood, 11 November, 2009.
*/
#include <winver.h>
#ifdef _WIN64
# define BITS "64"
#else
# define BITS "32"
#endif
1 VERSIONINFO
FILEVERSION 1,3,0,0
PRODUCTVERSION 1,3,0,0
FILEOS VOS_NT
FILETYPE VFT_DLL
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "Comments", "http://ansicon.adoxa.cjb.net/"
VALUE "CompanyName", "Jason Hood"
VALUE "FileDescription", "ANSI Console"
VALUE "FileVersion", "1.30"
VALUE "InternalName", "ANSI" BITS
VALUE "LegalCopyright", "Freeware"
VALUE "OriginalFilename", "ANSI" BITS ".dll"
VALUE "ProductName", "ANSICON"
VALUE "ProductVersion", "1.30"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04B0
}
}

541
ansicon.c Normal file
View File

@ -0,0 +1,541 @@
/*
ANSICON.c - ANSI escape sequence console driver.
Jason Hood, 21 to 23 October, 2005.
Original injection code was derived from Console Manager by Sergey Oblomov
(hoopoepg). Use of FlushInstructionCache came from www.catch22.net.
Additional information came from "Process-wide API spying - an ultimate hack",
Anton Bassov's article in "The Code Project" (use of OpenThread).
v1.01, 11 & 12 March, 2006:
-m option to set "monochrome" (grey on black);
restore original color on exit.
v1.10, 22 February, 2009:
ignore Ctrl+C/Ctrl+Break.
v1.13, 21 & 27 March, 2009:
alternate injection method, to work with DEP;
use Unicode.
v1.20, 17 to 21 June, 2009:
use a combination of the two injection methods;
test if ANSICON is already installed;
added -e (and -E) option to echo the command line (without newline);
added -t (and -T) option to type (display) files (with file name).
v1.21, 23 September, 2009:
added -i (and -u) to add (remove) ANSICON to AutoRun.
v1.24, 6 & 7 January, 2010:
no arguments to -t, or using "-" for the name, will read from stdin;
fix -t and -e when ANSICON was already loaded.
v1.25, 22 July, 2010:
added -IU for HKLM.
v1.30, 3 August to 7 September, 2010:
x64 support.
*/
#define PVERS "1.30"
#define PDATE "7 September, 2010"
#define UNICODE
#define _UNICODE
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500 // MinGW wants this defined for OpenThread
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <shellapi.h>
#include <tlhelp32.h>
#include <ctype.h>
#include <io.h>
#include "injdll.h"
#ifdef __MINGW32__
int _CRT_glob = 0;
#endif
#ifdef _WIN64
# define InjectDLL InjectDLL64
# define BITS "64"
#else
# define InjectDLL InjectDLL32
# define BITS "32"
#endif
#define CMDKEY TEXT("Software\\Microsoft\\Command Processor")
#define AUTORUN TEXT("AutoRun")
void help( void );
void display( LPCTSTR, BOOL );
LPTSTR skip_spaces( LPTSTR );
LPTSTR skip_arg( LPTSTR );
void process_autorun( TCHAR );
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 )
{
DWORD len;
CHAR dll[MAX_PATH];
len = GetModuleFileNameA( NULL, dll, sizeof(dll) );
while (dll[len-1] != '\\')
--len;
lstrcpyA( dll + len, "ANSI" BITS ".dll" );
InjectDLL( ppi, dll );
}
static HANDLE hConOut;
static CONSOLE_SCREEN_BUFFER_INFO csbi;
void get_original_attr( void )
{
hConOut = CreateFile( TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
GetConsoleScreenBufferInfo( hConOut, &csbi );
}
void set_original_attr( void )
{
SetConsoleTextAttribute( hConOut, csbi.wAttributes );
CloseHandle( hConOut );
}
DWORD CtrlHandler( DWORD event )
{
return (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT);
}
//int _tmain( int argc, TCHAR* argv[] )
int main( void )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR* cmd;
BOOL option;
BOOL opt_m;
BOOL installed;
HMODULE ansi;
int rc = 0;
int argc;
LPWSTR* argv = CommandLineToArgvW( GetCommandLineW(), &argc );
if (argc > 1)
{
if (lstrcmp( argv[1], TEXT("--help") ) == 0 ||
(argv[1][0] == '-' && (argv[1][1] == '?' || argv[1][1] == 'h')) ||
(argv[1][0] == '/' && argv[1][1] == '?'))
{
help();
return rc;
}
if (lstrcmp( argv[1], TEXT("--version") ) == 0)
{
_putts( TEXT("ANSICON (" BITS "-bit) version " PVERS " (" PDATE ").") );
return rc;
}
}
option = (argc > 1 && argv[1][0] == '-');
if (option && (_totlower( argv[1][1] ) == 'i' ||
_totlower( argv[1][1] ) == 'u'))
{
process_autorun( argv[1][1] );
return rc;
}
get_original_attr();
opt_m = FALSE;
if (option && argv[1][1] == 'm')
{
WORD attr = 7;
if (_istxdigit( argv[1][2] ))
{
attr = _istdigit( argv[1][2] ) ? argv[1][2] - '0'
: (argv[1][2] | 0x20) - 'a' + 10;
if (_istxdigit( argv[1][3]))
{
attr <<= 4;
attr |= _istdigit( argv[1][3] ) ? argv[1][3] - '0'
: (argv[1][3] | 0x20) - 'a' + 10;
}
}
SetConsoleTextAttribute( hConOut, attr );
opt_m = TRUE;
++argv;
--argc;
option = (argc > 1 && argv[1][0] == '-');
}
installed = (GetEnvironmentVariable( TEXT("ANSICON"), NULL, 0 ) != 0);
if (option && argv[1][1] == 'p')
{
// If it's already installed, there's no need to do anything.
if (installed)
;
else if (GetParentProcessInfo( &pi ))
{
pi.hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId );
pi.hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, pi.dwThreadId );
SuspendThread( pi.hThread );
Inject( &pi );
ResumeThread( pi.hThread );
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
else
{
_putts( TEXT("ANSICON: could not obtain the parent process.") );
rc = 1;
}
}
else
{
ansi = 0;
if (!installed)
ansi = LoadLibrary( TEXT("ANSI" BITS ".dll") );
if (option && (argv[1][1] == 't' || argv[1][1] == 'T'))
{
BOOL title = (argv[1][1] == 'T');
if (argc == 2)
{
argv[2] = L"-";
++argc;
}
for (; argc > 2; ++argv, --argc)
{
if (title)
_tprintf( TEXT("==> %s <==\n"), argv[2] );
display( argv[2], title );
if (title)
_puttchar( '\n' );
}
}
else
{
// Retrieve the original command line, skipping our name and the option.
cmd = skip_spaces( skip_arg( skip_spaces( GetCommandLine() ) ) );
if (opt_m)
cmd = skip_spaces( skip_arg( cmd ) );
if (cmd[0] == '-' && (cmd[1] == 'e' || cmd[1] == 'E'))
{
_fputts( cmd + 3, stdout );
if (cmd[1] == 'e')
_puttchar( '\n' );
}
else if (!isatty( 0 ) && *cmd == '\0')
{
display( TEXT("-"), FALSE );
}
else
{
if (*cmd == '\0')
{
cmd = _tgetenv( TEXT("ComSpec") );
if (cmd == NULL)
cmd = TEXT("cmd");
}
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
if (CreateProcess( NULL, cmd, NULL,NULL, TRUE, 0, NULL,NULL, &si, &pi ))
{
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)CtrlHandler, TRUE );
WaitForSingleObject( pi.hProcess, INFINITE );
}
else
{
*skip_arg( cmd ) = '\0';
_tprintf( TEXT("ANSICON: '%s' could not be executed.\n"), cmd );
rc = 1;
}
}
}
if (ansi)
FreeLibrary( ansi );
}
set_original_attr();
return rc;
}
void print_error( LPCTSTR name, BOOL title )
{
LPTSTR errmsg;
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, GetLastError(), 0, (LPTSTR)(LPVOID)&errmsg, 0, NULL );
if (!title)
_tprintf( TEXT("ANSICON: %s: "), name );
_fputts( errmsg, stdout );
LocalFree( errmsg );
}
// Display a file.
void display( LPCTSTR name, BOOL title )
{
// Handle the pipe differently.
if (*name == '-' && name[1] == '\0')
{
if (title)
_puttchar( '\n' );
int c;
while ((c = getchar()) != EOF)
putchar( c );
return;
}
HANDLE file = CreateFile( name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL );
if (file == INVALID_HANDLE_VALUE)
{
print_error( name, title );
return;
}
LARGE_INTEGER size;
GetFileSizeEx( file, &size );
if (size.QuadPart != 0)
{
HANDLE map = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
if (map)
{
if (title)
_puttchar( '\n' );
LARGE_INTEGER offset;
offset.QuadPart = 0;
do
{
DWORD len = (size.QuadPart > 65536) ? 65536 : size.LowPart;
LPVOID mem = MapViewOfFile( map, FILE_MAP_READ, offset.HighPart,
offset.LowPart, len );
if (mem)
{
fwrite( mem, 1, len, stdout );
UnmapViewOfFile( mem );
}
else
{
print_error( name, title );
break;
}
offset.QuadPart += len;
size.QuadPart -= len;
} while (size.QuadPart);
CloseHandle( map );
}
else
print_error( name, title );
}
CloseHandle( file );
}
// Add or remove ANSICON to AutoRun.
void process_autorun( TCHAR cmd )
{
HKEY cmdkey;
TCHAR ansicon[MAX_PATH+8];
LPTSTR autorun, ansirun;
DWORD len, type, exist;
BOOL inst;
len = GetModuleFileName( NULL, ansicon+2, MAX_PATH );
ansicon[0] = '&';
ansicon[1] = ansicon[2+len] = '"';
_tcscpy( ansicon + 3+len, L" -p" );
len += 6;
inst = (_totlower( cmd ) == 'i');
RegCreateKeyEx( (_istlower( cmd )) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
CMDKEY, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&cmdkey, &exist );
exist = 0;
RegQueryValueEx( cmdkey, AUTORUN, NULL, NULL, NULL, &exist );
autorun = malloc( exist + len * sizeof(TCHAR) + sizeof(TCHAR) );
// Let's assume there's sufficient memory.
if (exist > sizeof(TCHAR))
{
exist += sizeof(TCHAR);
RegQueryValueEx( cmdkey, AUTORUN, NULL, &type, (PBYTE)autorun, &exist );
ansirun = _tcsstr( autorun, ansicon+1 );
if (inst)
{
if (!ansirun)
{
_tcscpy( (LPTSTR)((PBYTE)autorun + exist - sizeof(TCHAR)), ansicon );
RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun,
exist + len*sizeof(TCHAR) );
}
}
else
{
if (ansirun)
{
if (ansirun == autorun && exist == len*sizeof(TCHAR))
RegDeleteValue( cmdkey, AUTORUN );
else
{
if (ansirun > autorun && ansirun[-1] == '&')
--ansirun;
else if (autorun[len-1] != '&')
--len;
memcpy( ansirun, ansirun + len, exist - len*sizeof(TCHAR) );
RegSetValueEx( cmdkey, AUTORUN, 0, type, (PBYTE)autorun,
exist - len*sizeof(TCHAR) );
}
}
}
}
else if (inst)
{
RegSetValueEx( cmdkey, AUTORUN, 0, REG_SZ, (PBYTE)(ansicon+1),
len*sizeof(TCHAR) );
}
free( autorun );
RegCloseKey( cmdkey );
}
// Search each process in the snapshot for id.
BOOL find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe )
{
BOOL fOk;
ppe->dwSize = sizeof(PROCESSENTRY32);
for (fOk = Process32First( snap, ppe ); fOk; fOk = Process32Next( snap, ppe ))
if (ppe->th32ProcessID == id)
break;
return fOk;
}
// Obtain the process and thread identifiers of the parent process.
BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi )
{
HANDLE hSnap;
PROCESSENTRY32 pe;
THREADENTRY32 te;
DWORD id = GetCurrentProcessId();
BOOL fOk;
hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD, id );
if (hSnap == INVALID_HANDLE_VALUE)
return FALSE;
find_proc_id( hSnap, id, &pe );
if (!find_proc_id( hSnap, pe.th32ParentProcessID, &pe ))
{
CloseHandle( hSnap );
return FALSE;
}
te.dwSize = sizeof(te);
for (fOk = Thread32First( hSnap, &te ); fOk; fOk = Thread32Next( hSnap, &te ))
if (te.th32OwnerProcessID == pe.th32ProcessID)
break;
CloseHandle( hSnap );
ppi->dwProcessId = pe.th32ProcessID;
ppi->dwThreadId = te.th32ThreadID;
return fOk;
}
// Return the first non-space character from cmd.
LPTSTR skip_spaces( LPTSTR cmd )
{
while ((*cmd == ' ' || *cmd == '\t') && *cmd != '\0')
++cmd;
return cmd;
}
// Return the end of the argument at cmd.
LPTSTR skip_arg( LPTSTR cmd )
{
while (*cmd != ' ' && *cmd != '\t' && *cmd != '\0')
{
if (*cmd == '"')
{
do
++cmd;
while (*cmd != '"' && *cmd != '\0');
if (*cmd == '\0')
--cmd;
}
++cmd;
}
return cmd;
}
void help( void )
{
_putts( TEXT(
"ANSICON by Jason Hood <jadoxa@yahoo.com.au>.\n"
"Version " PVERS " (" PDATE "). Freeware.\n"
"http://ansicon.adoxa.cjb.net/\n"
"\n"
#ifdef _WIN64
"Process ANSI escape sequences in Windows console programs.\n"
#else
"Process ANSI escape sequences in Win32 console programs.\n"
#endif
"\n"
"ansicon -i|I | -u|U\n"
"ansicon [-m[<attr>]] [-p | -e|E string | -t|T [file(s)] | program [args]]\n"
"\n"
" -i\t\tinstall - add ANSICON to the AutoRun entry\n"
" -u\t\tuninstall - remove ANSICON from the AutoRun entry\n"
" -I -U\t\tuse local machine instead of current user\n"
" -m\t\tuse grey on black (\"monochrome\") or <attr> as default color\n"
" -p\t\thook into the parent process\n"
" -e\t\techo string\n"
" -E\t\techo string, don't append newline\n"
" -t\t\tdisplay files (\"-\" for stdin), combined as a single stream\n"
" -T\t\tdisplay files, name first, blank line before and after\n"
" program\trun the specified program\n"
" nothing\trun a new command processor, or display stdin if redirected\n"
"\n"
"<attr> is one or two hexadecimal digits; please use \"COLOR /?\" for details."
) );
}

35
ansicon.rc Normal file
View File

@ -0,0 +1,35 @@
/*
ansicon.rc - Version resource for ansicon.exe.
Jason Hood, 11 November, 2009.
*/
#include <winver.h>
1 VERSIONINFO
FILEVERSION 1,3,0,0
PRODUCTVERSION 1,3,0,0
FILEOS VOS_NT
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "Comments", "http://ansicon.adoxa.cjb.net/"
VALUE "CompanyName", "Jason Hood"
VALUE "FileDescription", "ANSI Console"
VALUE "FileVersion", "1.30"
VALUE "InternalName", "ansicon"
VALUE "LegalCopyright", "Freeware"
VALUE "OriginalFilename", "ansicon.exe"
VALUE "ProductName", "ANSICON"
VALUE "ProductVersion", "1.30"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04B0
}
}

16
injdll.h Normal file
View File

@ -0,0 +1,16 @@
/*
injdll.h - Simple header file for injecting the DLL.
Jason Hood, 20 June, 2009.
*/
#ifndef INJDLL_H
#define INJDLL_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void InjectDLL32( LPPROCESS_INFORMATION, LPCSTR );
void InjectDLL64( LPPROCESS_INFORMATION, LPCSTR );
#endif

112
injdll32.c Normal file
View File

@ -0,0 +1,112 @@
/*
Inject code into the target process to load our DLL. The target thread
should be suspended on entry; it remains suspended on exit.
Initially I used the "stack" method of injection. However, this fails
when DEP is active, since that doesn't allow code to execute in the stack.
To overcome this I used the "CreateRemoteThread" method. However, this
would fail with Wselect, a program to assist batch files. Wselect runs,
but it has no output. As it turns out, removing the suspended flag would
make Wselect work, but it caused problems with everything else. So now I
allocate a section of memory and change the context to run from there. At
first I had an event to signal when the library was loaded, then the memory
was released. However, that wouldn't work with -p and CMD.EXE (4NT v8
worked fine). Since it's possible the DLL might start a process suspended,
I've decided to simply keep the memory.
*/
#include "injdll.h"
#ifdef _WIN64
#include "wow64.h"
TWow64GetThreadContext Wow64GetThreadContext;
TWow64SetThreadContext Wow64SetThreadContext;
#define CONTEXT WOW64_CONTEXT
#undef CONTEXT_CONTROL
#define CONTEXT_CONTROL WOW64_CONTEXT_CONTROL
#define GetThreadContext Wow64GetThreadContext
#define SetThreadContext Wow64SetThreadContext
#endif
DWORD LLA;
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCSTR dll )
{
CONTEXT context;
DWORD len;
LPVOID mem;
DWORD mem32;
#define CODESIZE 20
BYTE code[CODESIZE+MAX_PATH];
len = lstrlenA( dll ) + 1;
if (len > MAX_PATH)
return;
if (LLA == 0)
{
#ifdef _WIN64
extern HMODULE hKernel;
#define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
GETPROC( Wow64GetThreadContext );
GETPROC( Wow64SetThreadContext );
// Assume if one is defined, so is the other.
if (Wow64GetThreadContext == 0)
return;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
CopyMemory( code, dll, len - 7 ); // ...ANSI32.dll\0
CopyMemory( code + len - 7, "-LLA.exe", 9 ); // ...ANSI-LLA.exe\0
if (!CreateProcess( (char*)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi ))
return;
WaitForSingleObject( pi.hProcess, INFINITE );
GetExitCodeProcess( pi.hProcess, &LLA );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
#else
LLA = (DWORD)GetProcAddress( GetModuleHandleA( "kernel32.dll" ),
"LoadLibraryA" );
#endif
}
CopyMemory( code + CODESIZE, dll, len );
len += CODESIZE;
context.ContextFlags = CONTEXT_CONTROL;
GetThreadContext( ppi->hThread, &context );
mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
PAGE_EXECUTE_READWRITE );
mem32 = (DWORD)(DWORD_PTR)mem;
union
{
PBYTE pB;
PDWORD pL;
} ip;
ip.pB = code;
*ip.pB++ = 0x68; // push eip
*ip.pL++ = context.Eip;
*ip.pB++ = 0x9c; // pushf
*ip.pB++ = 0x60; // pusha
*ip.pB++ = 0x68; // push "path\to\ANSI32.dll"
*ip.pL++ = mem32 + CODESIZE;
*ip.pB++ = 0xe8; // call LoadLibraryA
*ip.pL++ = LLA - (mem32 + (ip.pB+4 - code));
*ip.pB++ = 0x61; // popa
*ip.pB++ = 0x9d; // popf
*ip.pB++ = 0xc3; // ret
WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
FlushInstructionCache( ppi->hProcess, mem, len );
context.Eip = mem32;
SetThreadContext( ppi->hThread, &context );
}

98
injdll64.c Normal file
View File

@ -0,0 +1,98 @@
/*
Inject code into the target process to load our DLL. The target thread
should be suspended on entry; it remains suspended on exit.
Initially I used the "stack" method of injection. However, this fails
when DEP is active, since that doesn't allow code to execute in the stack.
To overcome this I used the "CreateRemoteThread" method. However, this
would fail with Wselect, a program to assist batch files. Wselect runs,
but it has no output. As it turns out, removing the suspended flag would
make Wselect work, but it caused problems with everything else. So now I
allocate a section of memory and change the context to run from there. At
first I had an event to signal when the library was loaded, then the memory
was released. However, that wouldn't work with -p and CMD.EXE (4NT v8
worked fine). Since it's possible the DLL might start a process suspended,
I've decided to simply keep the memory.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void InjectDLL64( LPPROCESS_INFORMATION ppi, LPCSTR dll )
{
CONTEXT context;
DWORD len;
LPVOID mem;
DWORD64 LLA;
#define CODESIZE 92
static BYTE code[CODESIZE+MAX_PATH] = {
0,0,0,0,0,0,0,0, // original rip
0,0,0,0,0,0,0,0, // LoadLibraryA
0x9C, // pushfq
0x50, // push rax
0x51, // push rcx
0x52, // push rdx
0x53, // push rbx
0x55, // push rbp
0x56, // push rsi
0x57, // push rdi
0x41,0x50, // push r8
0x41,0x51, // push r9
0x41,0x52, // push r10
0x41,0x53, // push r11
0x41,0x54, // push r12
0x41,0x55, // push r13
0x41,0x56, // push r14
0x41,0x57, // push r15
0x48,0x83,0xEC,0x28, // sub rsp, 40
0x48,0x8D,0x0D,41,0,0,0, // lea ecx, "path\to\ANSI.dll"
0xFF,0x15,-49,-1,-1,-1, // call LoadLibraryA
0x48,0x83,0xC4,0x28, // add rsp, 40
0x41,0x5F, // pop r15
0x41,0x5E, // pop r14
0x41,0x5D, // pop r13
0x41,0x5C, // pop r12
0x41,0x5B, // pop r11
0x41,0x5A, // pop r10
0x41,0x59, // pop r9
0x41,0x58, // pop r8
0x5F, // pop rdi
0x5E, // pop rsi
0x5D, // pop rbp
0x5B, // pop rbx
0x5A, // pop rdx
0x59, // pop rcx
0x58, // pop rax
0x9D, // popfq
0xFF,0x25,-91,-1,-1,-1, // jmp original Rip
0, // dword alignment for LLA, fwiw
};
len = lstrlenA( dll ) + 1;
if (len > MAX_PATH)
return;
CopyMemory( code + CODESIZE, dll, len );
len += CODESIZE;
context.ContextFlags = CONTEXT_CONTROL;
GetThreadContext( ppi->hThread, &context );
mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
PAGE_EXECUTE_READWRITE );
LLA = (DWORD64)GetProcAddress( GetModuleHandleA( "kernel32.dll" ),
"LoadLibraryA" );
union
{
PBYTE pB;
PDWORD64 pL;
} ip;
ip.pB = code;
*ip.pL++ = context.Rip;
*ip.pL++ = LLA;
WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
FlushInstructionCache( ppi->hProcess, mem, len );
context.Rip = (DWORD64)mem + 16;
SetThreadContext( ppi->hThread, &context );
}

53
makefile Normal file
View File

@ -0,0 +1,53 @@
# Simple makefile for ANSICON.
# Jason Hood, 11 March, 2006. Updated 20 June, 2009.
# I've used TDM64 (gcc 4.5.0), 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, but will of course fail on the 64-bit.
CC = gcc
CFLAGS = -O2 -Wall
x86/%.o: %.c
$(CC) -m32 -c $(CFLAGS) $(CPPFLAGS) $< -o $@
x86/%v.o: %.rc
windres -U _WIN64 -F pe-i386 $< $@
x64/%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
x64/%v.o: %.rc
windres $< $@
all: ansicon32 ansicon64
ansicon32: x86/ansicon.exe x86/ANSI32.dll
ansicon64: x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll x64/ANSI-LLA.exe
x86/ansicon.exe: x86/ansicon.o x86/injdll32.o x86/ansiconv.o
$(CC) -m32 $+ -s -o $@
x86/ANSI32.dll: x86/ANSI.o x86/injdll32.o x86/ansiv.o
$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared
x64/ansicon.exe: x64/ansicon.o x64/injdll64.o x64/ansiconv.o
$(CC) $+ -s -o $@
x64/ANSI64.dll: x64/ANSI.o x64/injdll64.o x64/injdll32.o x64/ansiv.o
$(CC) $+ -s -o $@ -mdll -Wl,-shared
x64/ANSI32.dll: x86/ANSI32.dll
cmd /c copy x86\ANSI32.dll x64\ANSI32.dll
x64/ANSI-LLA.exe: ANSI-LLA.c
$(CC) -m32 $(CFLAGS) $< -s -o $@
x86/ansiconv.o: ansicon.rc
x86/ansiv.o: ansi.rc
x64/ansiconv.o: ansicon.rc
x64/ansiv.o: ansi.rc
clean:
-cmd /c "del x86\*.o x64\*.o"

236
readme.txt Normal file
View File

@ -0,0 +1,236 @@
ANSICON
Copyright 2005-2010 Jason Hood
Version 1.30. Freeware
===========
Description
===========
ANSICON provides ANSI escape sequences for Windows console programs. It
provides much the same functionality as `ANSI.SYS' does for MS-DOS.
============
Requirements
============
Windows 2000 Professional and later (it won't work with NT or 9X).
============
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 again with `-U') to remove
the AutoRun entry/ies, then removing the directory from PATH or deleting
the files. No other changes are made.
---------
Upgrading
---------
Delete ANSI.dll, it has been replaced with ANSI32.dll.
=====
Usage
=====
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. Passing the option `-p' (case sensitive) will enable the parent
process to recognise escapes (i.e. the command shell used to run ANSI-
CON). Use `-m' to set the current (and default) attribute to grey on
black ("monochrome"), or the attribute following the `m' (please use
`COLOR /?' for attribute values). The option `-e' will echo the command
line - the character after the `e' is ignored, the remainder is display-
ed verbatim; use `-E' to prevent a newline being written. The option
`-t' will display each file (or standard input if none or it is "-"), as
though they are a single file; `-T' will display the file name (in be-
tween "==> " and " <=="), a blank line (or an error message), the file
and another blank line. Anything else will be treated as a program and
its arguments. Eg: `ansicon -m30 -t file.ans' will display `file.ans'
using black on cyan as the default color.
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.
=========
Sequences
=========
The following escape sequences are recognised.
\e[#A CUU: CUrsor Up
\e[#B CUD: CUrsor Down
\e[#C CUF: CUrsor Forward
\e[#D CUB: CUrsor Backward
\e[#E CNL: Cursor Next Line
\e[#F CPL: Cursor Preceding Line
\e[#G CHA: Cursor Horizontal Absolute
\e[#;#H CUP: CUrsor Position
\e[#;#f HVP: Horizontal and Vertical Position
\e[s SCP: Save Cursor Position
\e[u RCP: Restore Cursor Position
\e[#J ED: Erase Display
\e[#K EL: Erase Line
\e[#L IL: Insert Lines
\e[#M DL: Delete Lines
\e[#@ ICH: Insert CHaracter
\e[#P DCH: Delete CHaracter
\e[#;#;#m SGM: Set Graphics Mode
`\e' represents the escape character (ASCII 27); `#' represents a
decimal number (optional, in most cases defaulting to 1). Regarding
SGM: bold will set the foreground intensity; underline and blink will
set the background intensity; conceal uses background as foreground.
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.
===========
Limitations
===========
The entire console buffer is used, not just the visible window.
If running CMD.EXE, its own COLOR will be the initial color.
===============
Version History
===============
Legend: + added, - bug-fixed, * changed.
1.30 - 7 September, 2010:
+ x64 version.
1.25 - 22 July, 2010:
- hook LoadLibraryEx (now CScript works);
- fixed -i when AutoRun existed, but was empty;
+ support for Windows 7;
+ -I (and -U) use HKEY_LOCAL_MACHINE.
1.24 - 7 January, 2010:
- fix -t and -e when ANSICON was already running;
+ read standard input if redirected with no arguments, if -t has no
files, or if the name is "-" (which also serves as a workaround for
programs that don't get hooked, such as CScript).
1.23 - 11 November, 2009:
- restore hooked functions when unloading;
- reverse the "bold" and "underline" settings;
* conceal characters by making foreground color same as background.
1.22 - 5 October, 2009:
- hook LoadLibrary to inject into applications started via association.
1.21 - 23 September, 2009:
+ -i (and -u) option to add (remove) entry to AutoRun value.
1.20 - 21 June, 2009:
* use another injection method;
+ create ANSICON environment variable;
+ -e (and -E) option to echo the command line (without newline);
+ -t (and -T) option to type (display) files (with file name).
1.15 - 17 May, 2009:
- fix output corruption for long (over 8192 characters) ANSI strings.
1.14 - 3 April, 2009:
- fix the test for an empty import section (eg. XCOPY now works).
1.13 - 21 & 27 March, 2009:
* use a new injection method (to work with DEP);
* use Unicode.
1.12 - 9 March, 2009:
- fix processing child programs (generate a relocatable DLL).
1.11 - 28 February, 2009:
- fix processing child programs (only use for console executables).
1.10 - 22 February, 2009:
- fix output corruption (buffer overflow in MyConsoleWriteW);
- recognise current screen attributes as current ANSI atrributes;
- ignore Ctrl+C and Ctrl+Break;
+ process child programs.
1.01 - 12 March, 2006:
* \e[m will restore original color, not set grey on black;
+ -m option to set default (and initial) color;
- restore original color on exit;
- disable escape processing when console has disabled processed output;
+ \e[5m (blink) is the same as \e[4m (underline);
- do not conceal control characters (0 to 31).
1.00 - 23 October, 2005:
+ initial release.
===============
Acknowledgments
===============
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'.
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.
Dmitry Menshikov, Marko Bozikovic and Philippe Villiers, for their
assistance in making the 64-bit version a reality.
=======
Contact
=======
mailto:jadoxa@yahoo.com.au
http://ansicon.adoxa.cjb.net/
Jason Hood
11 Buckle Street
North Rockhampton
Qld 4701
Australia
============
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 included.
==============================
Jason Hood, 7 September, 2010.

88
wow64.h Normal file
View File

@ -0,0 +1,88 @@
/*
wow64.h - Definitions for Wow64.
Mingw64/TDM does not include these Wow64 definitions.
*/
#ifndef WOW64_H
#define WOW64_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define WOW64_CONTEXT_i386 0x00010000
#define WOW64_CONTEXT_CONTROL (WOW64_CONTEXT_i386 | 0x00000001L)
#define WOW64_CONTEXT_INTEGER (WOW64_CONTEXT_i386 | 0x00000002L)
#define WOW64_CONTEXT_SEGMENTS (WOW64_CONTEXT_i386 | 0x00000004L)
#define WOW64_CONTEXT_FLOATING_POINT (WOW64_CONTEXT_i386 | 0x00000008L)
#define WOW64_CONTEXT_DEBUG_REGISTERS (WOW64_CONTEXT_i386 | 0x00000010L)
#define WOW64_CONTEXT_EXTENDED_REGISTERS (WOW64_CONTEXT_i386 | 0x00000020L)
#define WOW64_CONTEXT_FULL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS)
#define WOW64_CONTEXT_ALL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | \
WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS | \
WOW64_CONTEXT_EXTENDED_REGISTERS)
#define WOW64_SIZE_OF_80387_REGISTERS 80
#define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512
typedef struct _WOW64_FLOATING_SAVE_AREA {
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
BYTE RegisterArea[WOW64_SIZE_OF_80387_REGISTERS];
DWORD Cr0NpxState;
} WOW64_FLOATING_SAVE_AREA;
typedef WOW64_FLOATING_SAVE_AREA *PWOW64_FLOATING_SAVE_AREA;
typedef struct _WOW64_CONTEXT {
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
WOW64_FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];
} WOW64_CONTEXT;
typedef WOW64_CONTEXT *PWOW64_CONTEXT;
typedef BOOL WINAPI (*TWow64GetThreadContext)( HANDLE hThread, PWOW64_CONTEXT lpContext );
typedef BOOL WINAPI (*TWow64SetThreadContext)( HANDLE hThread, CONST WOW64_CONTEXT *lpContext );
#endif

BIN
x64/ANSI-LLA.exe Normal file

Binary file not shown.

BIN
x64/ANSI32.dll Normal file

Binary file not shown.

BIN
x64/ANSI64.dll Normal file

Binary file not shown.

BIN
x64/ansicon.exe Normal file

Binary file not shown.

BIN
x86/ANSI32.dll Normal file

Binary file not shown.

BIN
x86/ansicon.exe Normal file

Binary file not shown.