Batch File Potential
by blip
NOTICE: TO ALL CONCERNED Certain text files and messages contained on this site deal with activities and devices which would be in violation of various Federal, State, and local laws if actually carried out or constructed. The webmasters of this site do not advocate the breaking of any law. Our text files and message bases are for informational purposes only. We recommend that you contact your local law enforcement officials before undertaking any project based upon any information obtained from this or any other web site. We do not guarantee that any of the information contained on this system is correct, workable, or factual. We are not responsible for, nor do we assume any liability for, damages resulting from the use of any information on this site.
Disclaimer
The contents of this file are not to be and must not be used maliciously but instead simply become an intellectual curiosity and inform readers to potentially serious security problems. I hold no responsibility for what damage you or others may inflict or have damage inflicted upon; I hold responsibility for NOTHING. With that out of the way, let's begin!
Batch files are much more powerful than most may initially believe, with sufficient knowledge one could use them to introduce directly executable code into a system. I will demonstrate how this can be done with a harmless example and explore other ways to perform the same task that may or may not be better in some way.
There are two main ways one could go about doing this, the first being incredibly easier. The first method utilizes echo statements that redirect their output to a file, this file being used much like a script by using its contents for "console input" into a program instead of the default keyboard. The program used is called debug and is on every computer running windows or dos AFAIK unless the user manually deletes it, and can be used to write and execute stuff in memory among other things. The second method is more difficult to prepare, but does not require debug to be present or accessible (many school machines e.g. disallow access to it) to execute the hidden code as if it were a program they downloaded instead of the batch (it actually uses the batch to write out the program to disk). when the programs are executed, it would be a good idea to have them wipe the script and/or program file itself so undeletion attempts won't yield any clues.
The example program will be an implementation of a program that goes full screen and makes your screen flash random colors (though inevitably optimizable). First off it would be wise to be fairly familiar with x86 assembly language and how dos works in order to write your own programs to be run, but I'll try to explain how things work for those who aren't. Yes it is possible to write it in something like C++, but you must be aware that it has to run in dos (though it could use dpmi in windows) and its easiest to do with .com files. Exes have lovely headers that you must meddle with for full compatibility, mmm fun (you can't load a .exe into memory via debug enter statements and expect it to execute properly at all because the way exe headers are interpreted during loading).
The example batch file before we start:
@echo off
echo e100 B8 13 00 CD 10 E4 40 88 C3 E4 40 88 C7 F6 E3 30>\z.dbg
echo e110 DF 88 C1 BA C8 03 30 C0 EE BA DA 03 EC A8 08 75>>\z.dbg
echo e120 FB EC A8 08 74 FB BA C9 03 88 D8 EE 88 F8 EE 88>>\z.dbg
echo e130 C8 EE B4 01 CD 16 74 CD B8 03 00 CD 10 C3>>\z.dbg
echo g=100>>\z.dbg
echo q>>\z.dbg
debug <\z.dbg>nul
del \z.dbg
Basically what this does is make your monitor flash pseudo-random colors for every screen refresh until you hit a key, at which point it exits. There's a lot to be explained, however, to completely understand HOW it works from the ground up, knowing little or nothing of assembly or dos internals. Good thing I won't be explaining everything in excruciating detail.
To keep the batch file's size to a minimum, the program contained must also be as small as possible. Usually this means that you must use as many system calls as possible that are practical to do and tend not to do everything yourself. Granted, there are things you can't call the system to do for you, in which case the code should be further size optimized. In DOS, system calls are usually done by an assembly instruction mnemonic called INT, short for INTerrupt. For now, you can think of them as little black boxes that do what you want with the proper inputs and outputs until you read an assembly tutorial off somewhere where you'll realize there's really much more to it. Anyway, most software interrupts (usually used for system calls) take inputs in registers, which are like a select few speedy memory locations contained in the CPU itself. I guess I'd better explain and list the registers before I go further:
General Purpose (GP) registers:
AX - Accumulator
BX - Base
CX - Counter
DX - Displacement
BP - Base Pointer
SP - Stack Pointer
SI - Source Index
DI - Destination Index
Segment Registers (not explained here because they're not needed to understand the example, go to a tut for info):
CS - Code Segment
DS - Data Segment
ES - Extra Segment
FS - Extra Segment #2 (386+)
GS - Extra Segment #3 (386+)
SS - Stack Segment
Half of the GPregs (general purpose registers as I call them) can be broken up into byte-sized chunks and used as such. These would be the ones ending in X such as AX, its component registers being AH (Accumulator High, high byte of AX) and AL (Accumulator Low, low byte of AX). The remaining half of the group can only be accessed as 16-bit quantities. All GPregs can also be accessed as 32-bit entities, prefixed with E as in EAX for Extended Accumulator, beginning with the 386 (not like anyone cares, most people today haven't even heard of a 386).
I wrote the program above in debug, although you could do it in some symbolic assembler like nasm or fasm. Remember EVERYTHING in debug is either in hex or ascii. Here is a disassembly with corresponding addresses and hex encoded machine code eqivalents preceding each instruction mnemonic:
1370:0100 B81300 MOV AX,0013
1370:0103 CD10 INT 10
1370:0105 E440 IN AL,40
1370:0107 88C3 MOV BL,AL
1370:0109 E440 IN AL,40
1370:010B 88C7 MOV BH,AL
1370:010D F6E3 MUL BL
1370:010F 30DF XOR BH,BL
1370:0111 88C1 MOV CL,AL
1370:0113 BAC803 MOV DX,03C8
1370:0116 30C0 XOR AL,AL
1370:0118 EE OUT DX,AL
1370:0119 BADA03 MOV DX,03DA
1370:011C EC IN AL,DX
1370:011D A808 TEST AL,08
1370:011F 75FB JNZ 011C
1370:0121 EC IN AL,DX
1370:0122 A808 TEST AL,08
1370:0124 74FB JZ 0121
1370:0126 BAC903 MOV DX,03C9
1370:0129 88D8 MOV AL,BL
1370:012B EE OUT DX,AL
1370:012C 88F8 MOV AL,BH
1370:012E EE OUT DX,AL
1370:012F 88C8 MOV AL,CL
1370:0131 EE OUT DX,AL
1370:0132 B401 MOV AH,01
1370:0134 CD16 INT 16
1370:0136 74CD JZ 0105
1370:0138 B80300 MOV AX,0003
1370:013B CD10 INT 10
1370:013D C3 RET
The first instruction (MOV AX,0013) specifies the function number 00h in AH that sets the video mode, in this case it is mode 13h in AL which is a grainy graphics mode by today's standards of 320x200 with 256 colors. This mode is favored by some programmers because it is very convenient in ways which will not be discussed here. The mode number 13h also specifies whether or not to clear the screen according to bit7. If cleared (set to 0) as it is, the video BIOS clears the screen, otherwise it doesn't. After setting AX with the necessary parameters, it calls interrupt 10 to fulfill the video bios service request. Setting this mode in this way is a very short way of both clearing the screen and making the dos box go full screen if the program is running in windows. The next set of instructions at offsets 105h to 111h (the numbers after the colon) read two bytes from a timer port and perform simple calculations to make 3 pseudorandom bytes. The instructions at offsets 113h to 118h set the palette index to zero which starts off as black so later the palette values can be written, this is important to do every loop because after writing a palette value the index will autoincrement to index one which is not desired. Next, at offsets 119h to 124h, the program waits for a vertical retracing period to make its move. when a vertical retrace occurs, the computer can safely write to video memory, or in our case, the palette registers, without causing flickers or tearing or any other aesthetic nasties because this is one time when the video card is not actively drawing a picture to the monitor. Not every card supports this, but almost all do. There's a way to check it using some VESA calls to prevent it from looping infinitely during polling, but I opted to keep the program short and simple. After this, at offsets 126h to 131h the actual palette entry is written using the previously calculated pseudorandom numbers. Palette entries are by default six bits wide so the top two bits are ignored and each entry consists of separate red, green, and blue values that are written in that order. The bios is then called to see whether a key has been pressed, if not continue looping at offset 105h else set the video mode back to the most common text mode and exit using a RETurn instruction.
Ahh, now with that out of the way I can finally cover the second method. Beware that this is exceedingly unlikely to work if the batch file is sent using an ascii transfer instead of binary because it actually contains raw program code in segments of the batch file. For this reason and the fact that it most likely won't show up correctly on a web page I can't show the example batch file. But I can do the next best thing: guide you how to do it in the simplest editor ever. This idea was developed independently of, but later with help from, an apj9 article. As you know the dos copy command can copy files, but it can also copy to and from files and devices. In order to be able to type up a file's contents without an editor or without a picky one in dos, use copy con filename.ext and con stands for console being your keyboard or monitor depending on the direction of data flow. The program is then entered with alt+numeric keypad sequences.
However, the numbers you enter must be in decimal, not hex, and some characters aren't allowed for various reasons, and this includes also not being able to use them in the batch file. The disallowed characters are 0, 3, 6, 8, 10 (0Ah), 13 (0Dh), 16 (10h), 19 (13h), 26 (1Ah), and 27 (1Bh); the first is the null character and e.g. notepad with convert it to a space (32, 20h) if resaved, 3 is Ctrl-C which would exit the "editor", 6 I don't know, 8 is backspace, 13 and 10 can only be used together in that order by hitting enter, 16 and 19 I don't know, 26 tells the editor you're done, and 27 I don't know (my reference says so, so I'll take their word for it). Just by looking at the machine code dump you can see already that some of these are present, especially character 3. Moving some things around, doing some "unnecessary" calculations, and doing things in completely different ways can remove all instances of these illegal characters. Here's the code I've come up with, and it's almost 1.5 times as large as the previous code (I could have done better, but oh well):
1370:0100 30E4 XOR AH,AH
1370:0102 1F POP DS
1370:0103 B012 MOV AL,12
1370:0105 BB01FF MOV BX,FF01
1370:0108 9C PUSHF
1370:0109 40 INC AX
1370:010A FF9F3F01 CALL FAR [BX+013F]
1370:010E E440 IN AL,40
1370:0110 88C3 MOV BL,AL
1370:0112 E440 IN AL,40
1370:0114 88C7 MOV BH,AL
1370:0116 F6E3 MUL BL
1370:0118 30DF XOR BH,BL
1370:011A 88C1 MOV CL,AL
1370:011C BAC802 MOV DX,02C8
1370:011F FEC6 INC DH
1370:0121 30C0 XOR AL,AL
1370:0123 EE OUT DX,AL
1370:0124 BADA02 MOV DX,02DA
1370:0127 FEC6 INC DH
1370:0129 EC IN AL,DX
1370:012A D0E8 SHR AL,1
1370:012C A804 TEST AL,04
1370:012E 75F9 JNZ 0129
1370:0130 EC IN AL,DX
1370:0131 D0E8 SHR AL,1
1370:0133 A804 TEST AL,04
1370:0135 74F9 JZ 0130
1370:0137 BAC902 MOV DX,02C9
1370:013A FEC6 INC DH
1370:013C 88D8 MOV AL,BL
1370:013E EE OUT DX,AL
1370:013F 88F8 MOV AL,BH
1370:0141 EE OUT DX,AL
1370:0142 88C8 MOV AL,CL
1370:0144 EE OUT DX,AL
1370:0145 B401 MOV AH,01
1370:0147 CD16 INT 16
1370:0149 74C3 JZ 010E
1370:014B 30E4 XOR AH,AH
1370:014D B002 MOV AL,02
1370:014F 40 INC AX
1370:0150 BB01FF MOV BX,FF01
1370:0153 9C PUSHF
1370:0154 FF9F3F01 CALL FAR [BX+013F]
1370:0158 CD20 INT 20
To make the batch file, type copy con vret.bat at the prompt and hit enter, then type the following except spaces unless it says :
@echo off
echo 0 ALT+228 ALT+31 ALT+176 ALT+18 ALT+187 ALT+1 ALT+255 ALT+156 @ ALT+255 ALT+159 ? ALT+1 ALT+228 @ ALT+136 ALT+195 ALT+228 @ ALT+136 ALT+199 ALT+246 ALT+227 0 ALT+223 ALT+136 ALT+193 ALT+186 ALT+200 ALT+2 ALT+254 ALT+198 0 ALT+192 ALT+238 ALT+186 ALT+218 ALT+2 ALT+254 ALT+198 ALT+236 ALT+208 ALT+232 ALT+168 ALT+4 u ALT+249 ALT+236 ALT+208 ALT+232 ALT+168 ALT+4 t ALT+249 ALT+186 ALT+201 ALT+2 ALT+254 ALT+198 ALT+136 ALT+216 ALT+238 ALT+136 ALT+248 ALT+238 ALT+136 ALT+200 ALT+238 ALT+180 ALT+1 ALT+205 ALT+22 t ALT+195 0 ALT+228 ALT+176 ALT+2 @ ALT+187 ALT+1 ALT+255 ALT+156 ALT+255 ALT+159 ? ALT+1 ALT+205 > blah.com
blah
del blah.com
Now hit F6 or Ctrl-Z or Alt-26 (all do the same thing) and then hit enter.
Yes, that is one long echo statement so don't start others or hit enter until you're done entering the sequence. And there you have it!