Back to Packers and Unpackers
Man, I wish The Undertaker would USE the formamus.htm model... this would
spare me a little work editing is interesting 'packer-oriented' essays...
Well
enjoy this one too... don't underestimate the teachings that The Undertaker is
giving you!
TRAP Ver 1.13 by Christoph Gabler 11.09.97 - 07.01.98
EXPLORING A STUPID PROTECTION SCHEME
Opcode generators and selfchanging code
BY
THE UNDERTAKER -=BANDA=-
02 February 1998
Introduction -
In the Assembly '97 party I met a new friend called BLuTO. He has given
me this protector: trap.exe.
Well the author of this program tried to convince users by
saying "If you use this program your, target program is 100% safe from
Reversers". But this is a sort of joke: this is one of the most stupid
protectors I ever discovered.
Also this author is asking money for the registerd version of this junk
protector. If you have money send it to tha HCU , It will help you on long
term more than buying this stupid program. Actually everybody has to thank
all students and +crackers, because they are doing a great job educating
people all over the world.
It is true that this is WindowZ age. But if you are doing something, Do
it nicely nevertheless. Otherwise don't do it.
These kind of stupid programs will help micro$oft to dominate it's
"PLUG & PRAY" awful world.
Tools You Need -
SoftICE 2.80
Psedit
Debug
Brain (really useful, believe me, if you happen to have one use it!)
Ok lets start our session. First use trap.exe to protect a target COM file
that you have chosen.
Chose a COM file that is not big and keep it unpacked. Because this will
make things easy when debugging the "protected" program.
Now fire up Softice and use the Loader utility to load your target COM file.
LDR CO.COM (assuming that you have called it co.com, duh)
Now process(p) until you see the following instructions
XXXX:1125 8CD1 MOV CX,SS --> Save the SS to CX
XXXX:1127 BA99CB MOV DX,CB99
XXXX:112A 8ED2 MOV SS,DX --> ** (1)
XXXX:112C 33D2 XOR DX,DX
XXXX:112E 8ED1 MOV SS,CX --> ** (2)
XXXX:1130 8BCA MOV CX,DX
XXXX:1132 33D2 XOR DX,DX
XXXX:1134 B90005 MOV CX,0500
XXXX:1137 EB02 JMP 113B
(1) Quite strange code. Apparently the protector is trying to
change the Stack segment register with CB99.
As we learned early COM files can contain one segment
address for all segment registers.
This is a common trick to crash generic unpackers, like DEBUG.EXE.
So change the code inside the program by using Psedit to 43h (inc bx)
and 4Bh (dec bx), which is equivalent to a 'classical' NOP,NOP (90h,90h).
(2) Mmmmmm. Here the protector wants to restore the original SS.
Ok, since we did't change the SS previously we don't need to restore it
either, do we? Change the opcodes to 43h (inc bx) and 4Bh (dec bx),
which is equivalent to a 'classical' NOP,NOP (90h,90h).
I can say one thing these kind of lame SS tricks can -may be- prevent
some lamers. But you can't for sure stop any good reverser with this
kind of crap.
Ok straight ahead till.....
XXXX:113B 81F9E203 CMP CX,03E2
XXXX:113F 7458 JZ 1199 -- **
XXXX:1141 83C1FE ADD CX,-02
XXXX:1144 83C201 ADD DX,+01
XXXX:1147 EBEE JMP 1137
XXXX:1149 20DC AND AH,BL
The above loop will countinue until CX=3E2. So put a breakpoint where
you want to go and let's have a look there
BPX 1199
G
Process through the code until .....
XXXX:1184 1E PUSH DS --> Save DS
XXXX:1185 33DB XOR BX,BX
XXXX:1187 8EDB MOV DS,BX --> Point DS to Vector Table
XXXX:1189 F7160500 NOT WORD PTR [0005] --> ** (3)
XXXX:118D EB01 JMP 1190 --> ** (4) (6)
XXXX:118F 9AF7160500 CALL 0005:16F7 --> ** (5)
XXXX:1194 1F POP DS --> Restore the DS
XXXX:1195 EB22 JMP 11B9
(3) Now 0000:0005 is the location for INT 1 (Single Step) ISR routine, see,
he pointed the vector table! In this location is contained the
SEGMENT address for INT 1 ISR routine.
By NOT'ing the location the protector changes the SEGMENT address of INT 1.
This will cause most debuggers to hang. This will happen because most debuggers
use the INT 1 (Sigle Step) interrupt to trace through the target program.
Now change the Opcode to 4 NOPs using psedit, say 43 4B 42 4A (inc bx, dec bx,
inc dx, dec dx)
(4) This JMP is pointed to location 1190. But there does NOT seem to be any
location 1190 in the code.
This is probably a selfchangeing JUMP.
Once you execute the JUMP, Code 1190 will look like This.
(Read my previous essay about PROTEXE V2.11 to learn more about
self changing code):
XXXX:1190 F7160500 NOT WORD PTR [0005]
(5) Again XXXX:1190 contains a NOT instruction. This instruction is to
restore the previous SEGMENT address of INT 1. It is the 'noting'
technique, which goes like This...
When you start:
NOT - 101 ----> 11111010 (1's Complement)
And then again:
NOT - 11111010 ----> 101 (Original Value)
Ok we did not change our INT 1 SEGMENT address at all. Therefore we
don't need to change it back either, do we?
We will NOT need to change the opcode of this instruction. If we
do the following step (jumping over).
(6) Change the JUMP instruction to JUMP to location 1194. Code location
1194 contains the POP DS instruction. Change code to ....
XXXX:118D EB05 JMP 1194
(P) Now please process through the code until ......
XXXX:11FE 81F9E303 CMP CX,03E3
XXXX:1202 75FE JNZ 1202 --> JMP to a same location.
XXXX:1204 E81C00 CALL 1223 --> **
XXXX:1207 E421 IN AL,21
XXXX:1209 0C02 OR AL,02 --> Mask the KeyB IRQ
XXXX:120B E621 OUT 21,AL --> ** (7)
XXXX:120D EB53 JMP 1262
Above CALL will prepare the next instruction set to be executed. It
is more like an OPCODE GENARATOR. This is a very good trick, actually.
But its implementation inside this program lacks.
(T) Trace through the call and try to understand what is happening, this
is the fun part of this essay.
Again you will see some lame tricks like Keyboard masking.
(7) Change the opcode to 90h,90h (NOP,NOP)... a program protected this
way deserves simple silly nopping and nothing else...
(P) Process through the code until...
XXXX:1262 1E PUSH DS ---> Save DS
XXXX:1263 33C0 XOR AX,AX
XXXX:1265 8ED8 MOV DS,AX ---> Point Vector Table
XXXX:1267 F7160400 NOT WORD PTR [0004] ---> Change OFFSET of the ISR
XXXX:126B EB01 JMP 126E ---> Changeing JUMP
XXXX:126D 9AF7160400 CALL 0004:16F7 ---> Restore ISR OFFSET
XXXX:1272 1F POP DS ---> Restore DS
XXXX:1273 EB42 JMP 12B7
XXXX:1275 EB30 JMP 12A7
Well again you see the same trick used to change the OFFSET address of
the INT 1 ISR routine. Repeat the steps used to save the SEGMENT address
of the INT 1 ISR routine.
(P) Process through the code .....
XXXX:12B7 9C PUSHF ---> Save Flag Reg.
XXXX:12B8 58 POP AX ---> Get Flag Reg. into AX
XXXX:12B9 50 PUSH AX
XXXX:12BA 25FF0F AND AX,0FFF ---> Playing With Flags
XXXX:12BD 50 PUSH AX ---> Push Flag Reg.
XXXX:12BE 9D POPF ---> Restore New Flags.
Above part of the code is the check the TF is on. You already know how
to handle the TF flag. If you don't know, then you better read my
previous essay about PROTEXE V2.11.
Ohhhhhh... look here!
(P) Process through the code until .....
XXXX:12D7 9D POPF ---> Get Flags.
XXXX:12D8 B80016 MOV AX,1600
XXXX:12DB CD2F INT 2F ---> Install Status Of Win.
XXXX:12DD 0AC0 OR AL,AL ---> ZF=1 then goto 12F9
XXXX:12DF 7518 JNZ 12F9 ---> ** (8)
Lets carefully check the above code. After the JNZ instruction you will
see nothing less (and nothing more) than Protected mode instructions in your
SoftIce window.
So, the Protector tried to implement some protected mode debugging techniques
to prevent the reversing of his app.
But unfortunatly failed.
Actually using protected mode debugging facilites you can do lots
of things. I will discuss some of them in my future essay called
"Tips and Tricks For Protected Mode Debugging". Actually this essay
is halfway completed and you will be able to read it very soon.
Now lets go back to business...
(8) To avoid all these protected mode debugging techniques. Simply
change the JNZ to an unconditional JMP like this.
XXXX:12DF E9F500 JMP 13D7 (don't care for the code you are
overwriting with the third byte,
you're jumping anyway, don't you...)
Ok lets (P) Process the landing code until.....
XXXX:13D8 8CD1 MOV CX,SS
XXXX:13DA 8CD8 MOV AX,DS
XXXX:13DC BA99CB MOV DX,CB99
XXXX:13DF 8ED2 MOV SS,DX ---> Change the SS
XXXX:13E1 33D2 XOR DX,DX
XXXX:13E3 8ED8 MOV DS,AX
XXXX:13E5 8ED1 MOV SS,CX ---> Restore the SS
XXXX:13E7 8BCA MOV CX,DX
XXXX:13E9 8ED8 MOV DS,AX
Again you will see the SS register changing routines. Now you have
learned how to handle these stupid methods.
Ok Lets rock...
Now check the program down 7,8 lines & (P) process till...
XXXX:13F0 3BC3 CMP AX,BX
XXXX:13F2 7508 JNZ 13FC ---> ** (9)
XXXX:13F4 E421 IN AL,21
XXXX:13F6 24FD AND AL,FD ---> Unmask KeyB IRQ.
XXXX:13F8 E621 OUT 21,AL
XXXX:13FA EB09 JMP 1405
(9) This JNZ is checking the Segment registers for the same value. Once
we are Debugged the program. This causes a change for the values in
AX and in BX.
Simply change the JNZ to 90h,90h (NOP,NOP).
Now (P) Process through the code until you will reach RET(C3h). This RET
Instruction will take you to the unprotected code of your program.
Mmmmmmm. You have done it nicely...
Now you can use DEBUG.EXE to unprotect (It has never been protected!)
your target COM file.
If you don't know how to use DEBUG.EXE to unprotect ANY protected
file, then please read my own essay Unpack/unprotect com files
using debug.exe
FINAL NOTE - If anyone has a new protector. Send it to me as an attachment.
Don't pay a single cent for idiotical protectors. Protection
developers should try to use some new methods rather than use always the
same old dos tricks.
Readers can write to me at undertakerd@hotmail.com
!!!!!!!!!!!! Greetings to all +HCU Guys !!!!!!!!!!!!!
+ REST IN PEACE +
The Undertaker -=BANDA=- //SRI LANKA//
Back to Packers and Unpackers