New method to obtain 32-bit LoadLibraryW from 64-bit code, eliminating the need

for ANSI-LLW.exe.
Set the code page so ansicon.exe can display some strings properly.
Expand wildcards for -t.
VC6 can now compile the 32-bit version; use it for the release binaries.
Improvements to the VC makefile.
Describe the sequences in a bit more detail.
This commit is contained in:
Jason Hood 2012-11-24 23:41:29 +10:00
parent ef587f0dee
commit a52a46c9c1
12 changed files with 431 additions and 105 deletions

View File

@ -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 <windows.h>
int main( void )
{
return (DWORD)GetProcAddress( GetModuleHandle( "kernel32.dll" ),
"LoadLibraryW" );
}

20
ANSI.c
View File

@ -91,18 +91,23 @@
v1.53, 12 June, 2012:
fixed Update_GRM when running multiple processes (e.g. "cl /MP").
v1.60, 22 to 24 November, 2012:
alternative method to obtain LLW for 64->32 injection;
support for VC6 (remove section pragma, rename isdigit to is_digit).
*/
#include "ansicon.h"
#include "version.h"
#include <tlhelp32.h>
#define isdigit(c) ('0' <= (c) && (c) <= '9')
#define is_digit(c) ('0' <= (c) && (c) <= '9')
#ifdef __GNUC__
#define SHARED __attribute__((shared, section(".share")))
#define SHARED __attribute__((shared, section(".shared")))
#else
#pragma section(".shared", read,write,shared)
#pragma data_seg(".shared", "read,write,shared")
#pragma data_seg()
#define SHARED __declspec(allocate(".shared"))
#endif
@ -228,6 +233,9 @@ SHARED DWORD s_flag;
#define GRM_INIT 1
#define GRM_EXIT 2
#ifdef _WIN64
SHARED DWORD LLW32;
#endif
// Wait for the child process to finish, then update our GRM to the child's.
@ -846,7 +854,7 @@ ParseAndPrintString( HANDLE hDev,
}
else if (state == 3)
{
if (isdigit( *s ))
if (is_digit( *s ))
{
es_argc = 0;
es_argv[0] = *s - '0';
@ -873,7 +881,7 @@ ParseAndPrintString( HANDLE hDev,
}
else if (state == 4)
{
if (isdigit( *s ))
if (is_digit( *s ))
{
es_argv[es_argc] = 10 * es_argv[es_argc] + (*s - '0');
}
@ -1775,7 +1783,7 @@ void OriginalAttr( void )
// and terminated.
//-----------------------------------------------------------------------------
__declspec(dllexport) // to stop MinGW exporting everything
__declspec(dllexport) // just to stop MinGW exporting everything
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
BOOL bResult = TRUE;

133
ansicon.c
View File

@ -64,15 +64,21 @@
v1.52, 10 April, 2012:
fixed running "cmd" if "ComSpec" is not defined;
pass process & thread identifiers on the command line (for x86->x64).
v1.60, 22 & 24 November, 2012:
set the code page to convert strings correctly;
expand wildcards for -t;
write the date if appending to the log.
*/
#define PDATE L"12 June, 2012"
#define PDATE L"24 November, 2012"
#include "ansicon.h"
#include "version.h"
#include <tlhelp32.h>
#include <ctype.h>
#include <io.h>
#include <locale.h>
#ifdef __MINGW32__
int _CRT_glob = 0;
@ -96,6 +102,7 @@ void display( LPCTSTR, BOOL );
void print_error( LPCTSTR, ... );
LPTSTR skip_spaces( LPTSTR );
void get_arg( LPTSTR, LPTSTR*, LPTSTR* );
void get_file( LPTSTR, LPTSTR*, LPTSTR* );
void process_autorun( TCHAR );
@ -103,6 +110,12 @@ BOOL find_proc_id( HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe );
BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR );
// The DLL shares this variable, so injection requires it here.
#ifdef _WIN64
DWORD LLW32;
#endif
// Find the name of the DLL and inject it.
BOOL Inject( LPPROCESS_INFORMATION ppi, BOOL* gui, LPCTSTR app )
{
@ -199,6 +212,10 @@ int main( void )
GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
log_level = _wtoi( logstr );
// Using "" for setlocale uses the system ANSI code page.
sprintf( (LPSTR)logstr, ".%u", GetConsoleOutputCP() );
setlocale( LC_CTYPE, (LPSTR)logstr );
#ifdef _WIN64
if (*arg == '-' && arg[1] == 'P')
{
@ -212,8 +229,8 @@ int main( void )
}
#endif
if (log_level && !(log_level & 8))
DEBUGSTR( 1, NULL ); // create a new file
if (log_level)
DEBUGSTR( 1, NULL ); // start a new session
installed = (GetEnvironmentVariable( L"ANSICON_VER", NULL, 0 ) != 0);
// If it's already installed, remove it. This serves two purposes: preserves
@ -235,8 +252,7 @@ int main( void )
case 'l':
SetEnvironmentVariable( L"ANSICON_LOG", arg + 2 );
log_level = _wtoi( arg + 2 );
if (!(log_level & 8)) // unless told otherwise
DEBUGSTR( 1, NULL ); // create a new file
DEBUGSTR( 1, NULL ); // create a session
break;
case 'i':
@ -285,7 +301,7 @@ int main( void )
a = -a;
a = ((a >> 4) & 15) | ((a & 15) << 4);
}
SetConsoleTextAttribute( hConOut, a );
SetConsoleTextAttribute( hConOut, (WORD)a );
SetEnvironmentVariable( L"ANSICON_DEF", NULL );
break;
}
@ -316,14 +332,14 @@ arg_out:
{
if (*cmd == '\0')
{
cmd = _wgetenv( L"ComSpec" );
if (cmd == NULL)
if (GetEnvironmentVariable( L"ComSpec", arg, MAX_PATH ))
cmd = arg;
else
{
// CreateProcessW writes to the string, so can't simply point to "cmd".
static TCHAR cmdstr[] = L"cmd";
cmd = cmdstr;
}
arg = cmd;
}
ZeroMemory( &si, sizeof(si) );
@ -369,7 +385,7 @@ arg_out:
else // (*arg == 't' || *arg == 'T')
{
BOOL title = (*arg == 'T');
get_arg( arg, &argv, &cmd );
get_file( arg, &argv, &cmd );
if (*arg == '\0')
wcscpy( arg, L"-" );
do
@ -382,7 +398,7 @@ arg_out:
}
else
display( arg, title );
get_arg( arg, &argv, &cmd );
get_file( arg, &argv, &cmd );
} while (*arg);
}
@ -650,6 +666,101 @@ void get_arg( LPTSTR arg, LPTSTR* argv, LPTSTR* cmd )
}
int glob_sort( const void* a, const void* b )
{
return lstrcmpi( *(LPCTSTR*)a, *(LPCTSTR*)b );
}
// As get_arg, but expand wildcards.
void get_file( LPTSTR arg, LPTSTR* argv, LPTSTR* cmd )
{
HANDLE fh, in;
WIN32_FIND_DATA fd;
LPTSTR path;
int size;
char buf[1024];
static LPTSTR name;
static LPTSTR* glob;
static int globbed;
if (globbed != 0)
{
if (glob[globbed] == NULL)
{
free( glob );
globbed = 0;
}
else
{
wcscpy( name, glob[globbed++] );
return;
}
}
get_arg( arg, argv, cmd );
if (wcspbrk( arg, L"*?" ) != NULL)
{
fh = FindFirstFile( arg, &fd );
if (fh != INVALID_HANDLE_VALUE)
{
size = 0;
do
{
if (! (fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_HIDDEN)))
{
++globbed;
size += (int)wcslen( fd.cFileName ) + 1;
}
} while (FindNextFile( fh, &fd ));
FindClose( fh );
if (globbed != 0)
{
for (path = name = arg; *path != '\0'; ++path)
if (*path == '\\' || *path == '/')
name = path + 1;
glob = malloc( (globbed + 1) * sizeof(LPTSTR) + TSIZE(size) );
path = (LPTSTR)(glob + globbed + 1);
globbed = 0;
fh = FindFirstFile( arg, &fd );
do
{
if (! (fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_HIDDEN)))
{
// Ignore apparent binary files.
wcscpy( name, fd.cFileName );
in = CreateFile( arg, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if (in != INVALID_HANDLE_VALUE)
{
ReadFile( in, buf, sizeof(buf), (LPVOID)&size, NULL );
CloseHandle( in );
if (memchr( buf, 0, size ) != NULL)
continue;
}
size = (int)wcslen( fd.cFileName ) + 1;
memcpy( path, fd.cFileName, TSIZE(size) );
glob[globbed++] = path;
path += size;
}
} while (FindNextFile( fh, &fd ));
FindClose( fh );
glob[globbed] = NULL;
qsort( glob, globbed, sizeof(LPTSTR), glob_sort );
wcscpy( name, glob[0] );
globbed = 1;
}
}
}
}
void help( void )
{
_putws(

View File

@ -12,7 +12,11 @@
#endif
#define WIN32_LEAN_AND_MEAN
#ifdef _WIN64
#define _WIN32_WINNT 0x0600 // MinGW-w64 wants this defined for Wow64 stuff
#else
#define _WIN32_WINNT 0x0500 // MinGW wants this defined for OpenThread
#endif
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -18,11 +18,12 @@
#include "ansicon.h"
#ifdef _WIN64
#if defined(__MINGW64__) || (defined(_MSC_VER) && _MSC_VER <= 1400)
#ifndef WOW64_CONTEXT_ALL
#include "wow64.h"
TWow64GetThreadContext Wow64GetThreadContext;
TWow64SetThreadContext Wow64SetThreadContext;
#define IMPORT_WOW64
#endif
#define CONTEXT WOW64_CONTEXT
@ -30,12 +31,99 @@ TWow64SetThreadContext Wow64SetThreadContext;
#define CONTEXT_CONTROL WOW64_CONTEXT_CONTROL
#define GetThreadContext Wow64GetThreadContext
#define SetThreadContext Wow64SetThreadContext
#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 address of the 32-bit LoadLibraryW function from 64-bit code. This
was originally done via executing a helper program (ANSI-LLW.exe), but for
some reason, virus scanners really didn't like it (even when I rewrote it in
assembly so it was 1024 bytes and literally two instructions, virustotal
still had three scanners complaining). Now I do it the "hard" way - load the
32-bit kernel32.dll directly and search the exports. Even worse, it seems
Wow64 loads kernel32.dll at a different base address each boot (at least, I
hope it only changes each boot). Fortunately, loading the DLL as an image in
64-bit code seems to use the 32-bit address.
*/
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 & 0xFFFF0000);
// Tests to make sure we're looking at a module image (the 'MZ' header)
pDosHeader = (PIMAGE_DOS_HEADER)base;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
DEBUGSTR( 1, L"Image has no DOS header!" );
return FALSE;
}
// The MZ header has a pointer to the PE header
pNTHeader = MakeVA( PIMAGE_NT_HEADERS32, pDosHeader->e_lfanew );
// One more test to make sure we're looking at a "PE" image
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
DEBUGSTR( 1, L"Image has no NT header!" );
return FALSE;
}
// We now have a valid pointer to the module's PE header.
// Get a pointer to its exports section.
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!" );
return FALSE;
}
LLW32 = MakeVA( DWORD, fun_table[ord_table[pLLW - name_table]] );
FreeLibrary( kernel32 );
return TRUE;
}
#else
DWORD LLW32;
#endif
DWORD LLW;
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
{
CONTEXT context;
@ -54,12 +142,21 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
if (len > TSIZE(MAX_PATH))
return;
if (LLW == 0)
if (LLW32 == 0)
{
HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
#ifdef _WIN64
#ifdef __MINGW64__
if (!get_LLW32())
return;
#else
LLW32 = (DWORD)GetProcAddress( GetModuleHandleA( "kernel32.dll" ),
"LoadLibraryW" );
#endif
}
#ifdef IMPORT_WOW64
if (Wow64GetThreadContext == 0)
{
#define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
GETPROC( Wow64GetThreadContext );
GETPROC( Wow64SetThreadContext );
// Assume if one is defined, so is the other.
@ -68,30 +165,8 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
DEBUGSTR( 1, L"Failed to get pointer to Wow64GetThreadContext.\n" );
return;
}
#endif
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\".\n", (LPCTSTR)code );
return;
}
WaitForSingleObject( pi.hProcess, INFINITE );
GetExitCodeProcess( pi.hProcess, &LLW );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
#else
LLW = (DWORD)GetProcAddress( hKernel, "LoadLibraryW" );
#endif
}
CopyMemory( code + CODESIZE, dll, len );
len += CODESIZE;
@ -111,7 +186,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
*ip.pB++ = 0x68; // push L"path\to\ANSI32.dll"
*ip.pL++ = mem32 + CODESIZE;
*ip.pB++ = 0xe8; // call LoadLibraryW
*ip.pL++ = LLW - (mem32 + (DWORD)(ip.pB+4 - code));
*ip.pL++ = LLW32 - (mem32 + (DWORD)(ip.pB+4 - code));
*ip.pB++ = 0x61; // popa
*ip.pB++ = 0x9d; // popf
*ip.pB++ = 0xc3; // ret

View File

@ -10,6 +10,9 @@
#
# 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
@ -33,7 +36,7 @@ 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
ansicon64: x64 x64/ansicon.exe x64/ANSI64.dll x64/ANSI32.dll
x86:
cmd /c "mkdir x86"
@ -42,7 +45,7 @@ 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
$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000
x64:
cmd /c "mkdir x64"
@ -51,13 +54,10 @@ 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
$(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
x64/ANSI-LLW.exe: ANSI-LLW.c
$(CC) -m32 $(CFLAGS) $< -s -o $@
$(CC) -m32 $+ -s -o $@ -mdll -Wl,-shared,--image-base,0xAC0000
x86/ansicon.o: version.h
x86/ANSI.o: version.h

View File

@ -7,12 +7,22 @@
# 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.
# 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.
#BITS = 32
#BITS = 64
!IFNDEF BITS
!IF "$(CPU)" == "AMD64" || "$(PLATFORM)" == "x64"
BITS = 64
!ELSE
BITS = 32
!ENDIF
!ENDIF
!IF $(BITS) == 32
DIR = x86
@ -24,12 +34,23 @@ DIR = x64
!ENDIF
!ENDIF
CC = cl
CFLAGS = /nologo /W3 /Ox /GF /D_CRT_SECURE_NO_WARNINGS
LIBS = advapi32.lib user32.lib
# This is required for the 2003 Platform SDK, but not for Visual Studio 2010.
#LIBS64 = bufferoverflowu.lib
!IF "$(_NMAKE_VER)" == "7.00.8882"
LIBS64 = bufferoverflowu.lib
# The 2003 Toolkit doesn't have MSVCRT.LIB (but VC98 does).
!IF $(BITS) == 32 && !DEFINED(SHARE) && !DEFINED(MSVCDIR)
SHARE =
!ENDIF
!ENDIF
# Link with MSVCRT.LIB by default.
!IFNDEF SHARE
SHARE = /MD
!ENDIF
CC = cl
CFLAGS = /nologo /W3 /Ox /GF $(SHARE) /D_CRT_SECURE_NO_WARNINGS
LIBS = advapi32.lib user32.lib
X86OBJS = x86\proctype.obj x86\injdll32.obj x86\util.obj
X64OBJS = x64\proctype.obj x64\injdll64.obj x64\injdll32.obj x64\util.obj
@ -44,31 +65,28 @@ all: ansicon$(BITS)
ansicon32: x86 x86\ansicon.exe x86\ANSI32.dll x64\ANSI32.dll
ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll x64\ANSI-LLW.exe
ansicon64: x64 x64\ansicon.exe x64\ANSI64.dll
x86:
mkdir x86
x86\ansicon.exe: x86\ansicon.obj $(X86OBJS) x86\ansicon.res
$(CC) /nologo /Fe$@ $** $(LIBS)
$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) /link /filealign:512
x86\ANSI32.dll: x86\ANSI.obj $(X86OBJS) x86\ansi.res
$(CC) /nologo /LD /Fe$@ $** $(LIBS)
$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512
x64:
mkdir x64
x64\ansicon.exe: x64\ansicon.obj $(X64OBJS) x64\ansicon.res
$(CC) /nologo /Fe$@ $** $(LIBS) $(LIBS64)
$(CC) /nologo $(SHARE) /Fe$@ $** $(LIBS) $(LIBS64)
x64\ANSI64.dll: x64\ANSI.obj $(X64OBJS) x64\ansi.res
$(CC) /nologo /LD /Fe$@ $** $(LIBS) $(LIBS64)
$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) $(LIBS64) /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 /LD /Fe$@ $** $(LIBS)
x64\ANSI-LLW.exe: ANSI-LLW.c
$(CC) $(CFLAGS) /Fe$@ /Fo$*.obj $? $(LIBS64)
$(CC) /nologo $(SHARE) /LD /Fe$@ $** $(LIBS) /link /base:0xAC0000 /section:.shared,s /filealign:512
ansicon.c: ansicon.h version.h
ansicon.rc: version.h
@ -86,3 +104,6 @@ x64\proctype32.obj: proctype.c
clean:
-del $(DIR)\*.obj $(DIR)\*.res $(DIR)\*.lib $(DIR)\*.exp
!IF $(BITS) == 32
-del x64\ansi32.obj x64\proctype32.obj
!ENDIF

View File

@ -3,7 +3,7 @@
Copyright 2005-2012 Jason Hood
Version 1.53. Freeware
Version 1.60. Freeware
===========
@ -18,7 +18,8 @@
Requirements
============
Windows 2000 Professional and later (it won't work with NT or 9X).
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).
============
@ -39,7 +40,7 @@
---------
Delete ANSI.dll, it has been replaced with ANSI32.dll.
Delete ANSI-LLA.dll, it has been replaced with ANSI-LLW.dll.
Delete ANSI-LLA.exe/ANSI-LLW.exe, they are no longer needed.
Uninstall a pre-1.50 version and reinstall with this version.
@ -182,7 +183,8 @@
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.
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
@ -274,6 +276,13 @@
Legend: + added, - bug-fixed, * changed.
1.60 - 24 November, 2012:
* new method to get the 32-bit LoadLibraryW address from 64-bit code.
This removes the need for ANSI-LLW.exe, which caused lots of virus
warnings, for some reason.
- set the code page to display some file names properly;
+ expand wildcards for -t (ignoring directories and hidden/binary files).
1.53 - 12 June, 2012:
- fix for multiple simultaneous process creation (e.g. "cl /MP ...").
@ -432,8 +441,10 @@
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.
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.
==========================
Jason Hood, 12 June, 2012.
==============================
Jason Hood, 24 November, 2012.

118
sequences.txt Normal file
View File

@ -0,0 +1,118 @@
ANSICON
Version 1.60
This is a complete list of the ANSI escape sequences recognised by ANSICON,
roughly ordered by function. The initial escape character is assumed.
[m restore default color (and intensity)
[0m as above
[...m set attributes (any of these numbers, separated by semicolons):
0 all attributes off
1 bold (foreground is intense)
4 underline (background is intense)
5 blink (background is intense)
7 reverse video
8 concealed (foreground becomes background)
22 bold off (foreground is not intense)
24 underline off (background is not intense)
25 blink off (background is not intense)
27 normal video
28 concealed off
30 foreground black
31 foreground red
32 foreground green
33 foreground yellow
34 foreground blue
35 foreground magenta
36 foreground cyan
37 foreground white
39 default foreground (using current intensity)
40 background black
41 background red
42 background green
43 background yellow
44 background blue
45 background magenta
46 background cyan
47 background white
49 default background (using current intensity)
[J erase from cursor to the end of display
[0J as above
[1J erase from the start of diplay to cursor (inclusive)
[2J erase display and move cursor to the top-left
[K erase from cursor to the end of line
[0K as above
[1K erase from the start of line to cursor (inclusive)
[2K erase line
[X erase one character
[#X erase # characters
[L insert one blank line
[#L insert # blank lines
[M delete one line
[#M delete # lines
[P delete one character
[#P delete # characters
[@ insert one blank character
[#@ insert # blank characters
[A move cursor up one line
[#A move cursor up # lines
[B move cursor down one line
[#B move cursor down # lines
[C move cursor right one character
[#C move cursor right # characters
[D move cursor left one character
[#D move cursor left # characters
[k move cursor up one line
[#k move cursor up # lines
[e move cursor down one line
[#e move cursor down # lines
[a move cursor right one character
[#a move cursor right # characters
[j move cursor left one character
[#j move cursor left # characters
[E move cursor down one line and to first column
[#E move cursor down # lines and to first column
[F move cursor up one line and to first column
[#F move cursor up # lines and to first column
[G move cursor to first column
[#G move cursor to column #
[` move cursor to first column
[#` move cursor to column #
[d move cursor to first line
[#d move cursor to line #
[H move cursor to top-left
[#H move cursor to line # and first column
[#;#H move cursor to line #, column #
[f move cursor to top-left
[#f move cursor to line # and first column
[#;#f move cursor to line #, column #
[s save cursor position
[u move cursor to saved position
[?25h show cursor
[?25l hide cursor
[5n sends "\e[0n" to console input (where \e is escape)
[6n sends "\e[#;#R" (line & column) to console input
[21t sends "\e]lTitle\e\" (the console's window title) to console input
]0;TitleST
sets the console title to "Title"; ST (string terminator) is either
character 7 (BEL) or escape and backslash

2
util.c
View File

@ -55,7 +55,7 @@ void DEBUGSTR( int level, LPTSTR szFormat, ... )
}
if (szFormat == NULL)
{
file = fopen( tempfile, "wt" );
file = fopen( tempfile, (log_level & 8) ? "at" : "wt" );
if (file != NULL)
{
SYSTEMTIME now;

View File

@ -2,8 +2,8 @@
version.h - Version defines.
*/
#define PVERS L"1.53" // wide string
#define PVERSA "1.53" // ANSI string (windres 2.16.91 didn't like L)
#define PVERE L"153" // wide environment string
#define PVEREA "153" // ANSI environment string
#define PVERB 1,5,3,0 // binary (resource)
#define PVERS L"1.60" // wide string
#define PVERSA "1.60" // ANSI string (windres 2.16.91 didn't like L)
#define PVERE L"160" // wide environment string
#define PVEREA "160" // ANSI environment string
#define PVERB 1,6,0,0 // binary (resource)

View File

@ -1,7 +1,7 @@
/*
wow64.h - Definitions for Wow64.
Mingw64/TDM does not include these Wow64 definitions.
The 2003 Platform SDK does not include these Wow64 definitions.
*/
#ifndef WOW64_H