Category : Assembly Language Source Code
Archive   : UNEXEP10.ZIP
Filename : UNEXEPAC.ASM

 
Output of file : UNEXEPAC.ASM contained in archive : UNEXEP10.ZIP
; Unpacks EXEPACKed files. Uses MS embedded unpacker, after installing a few
; position independant patches in it (to make it build the relocation table).
; Note that the EXEPACK process round the image size to paragraph boundaries,
; i e EXEPACK + UNEXEPAC may add up to 15 pad bytes at the file end.

; Released to the Public Domain by Dan Norstedt 1991

; Version 1.0

; Build by: MASM UNEXEPAC;
; LINK UNEXEPAC;
; EXE2BIN UNEXEPAC UNEXEPAC.COM

CODE SEGMENT PUBLIC
ASSUME CS:CODE,DS:CODE

ORG 100H

START: CLD
MOV DI,Offset ZERBUF
XOR AX,AX
MOV CH,1
REP STOSW ; Set up a pad block (for reloc table)
CMP Byte Ptr DS:[5DH],20H ; Any argument?
JZ READIN
MOV DX,Offset USETXT ; Display usage text
JMP OUTMSG
USETXT DB "Usage: UNEXEPAC unpacked.EXE$"

WRKSTK:

OUTMS2: JMP OUTMSG

READNX: MOV AX,DS
ADD AX,0F80H
MOV DS,AX ; Adjust to next buffer
SUB AX,Word Ptr CS:[2] ; Overflow?
MOV DX,Offset TOOTXT
JAE OUTMS2
MOV CX,AX ; No, how much more can we read in?
SHL CX,1
SHL CX,1
SHL CX,1
SHL CX,1
CMP AX,0F80H ; Has CX a valid value < F800
JB READIX ; Yes, use it
READIN: MOV CX,0F800H ; Set up maximum read in chunk size
READIX: MOV SP,Offset WRKSTK ; Change stack to safe place:init code
MOV AH,3FH
XOR BX,BX
MOV DX,Offset BUFFER ; Read in data
INT 21H
MOV DX,Offset REATXT
JC OUTMS2
CMP AX,CX ; Got all we asked for?
JZ READNX ; Yes, try to get more
MOV AX,CS
ADD AX,Word Ptr CS:[BUFFER+08H] ; Get load image offset (PARA)
ADD AX,(Offset BUFFER-Offset START+100H)/10H-10H ; Buffer offset
MOV ES,AX ; Save faked PSP paragraph
ADD AX,10H
MOV Word Ptr CS:[EXEBASE],AX ; Save load image offset
ADD AX,Word Ptr CS:[BUFFER+16H]
MOV DS,AX ; Save faked CS
MOV SI,Word Ptr CS:[BUFFER+14H] ; Get faked IP
CMP Word Ptr [SI-2],"BR" ; Check for EXEPACK signature
MOV DX,Offset NOPTXT
JNZ OUTMSG ; Isn't EXEPACKed, tell user
CMP Word Ptr CS:[BUFFER+06H],0 ; Any relocation entries?
JNZ OUTMSG ; Yes, we can't handle it
CLD
MOV CX,100H ; Patch exe unpacker code
FINDEX: LODSB
CMP AL,03H ; Find code where exe unpacker
LOOPNZ FINDEX ; is about to transfer control
CMP Word Ptr [SI],01F0H ; to the now unpacked program
LOOPNZ FINDEX
JNZ OUTMSG
MOV Byte Ptr [SI-1],0EAH ; Replace it by a JMP Far
MOV Word Ptr [SI],Offset UNPDON ; straight to our own code
LODSW
MOV Word Ptr [SI],CS
MOV Byte Ptr [SI+2],9AH ; Use overflow to a CALL Far
MOV Word Ptr [SI+3],Offset WRIREL ; island to our reloc table
MOV Word Ptr [SI+5],CS ; write routine
MOV Byte Ptr [SI+7],0C3H ; RET Near
MOV BX,SI ; Save call island offset
MOV SI,Word Ptr CS:[BUFFER+14H] ; Reload exe unpacker offset
MOV CX,100H
FINDRE: LODSB
CMP AL,26H ; Look for ADD ES:[DI],DX
FINDRX: LOOPNZ FINDRE
JCXZ GOAHEA
CMP Word Ptr [SI],1D01H
JNZ FINDRX
MOV Byte Ptr [SI-1],0E8H ; Replace it to CALL Near to
SUB BX,SI ; our call island
MOV [SI],BX
ADD BX,SI
JMP Short FINDRX ; Repeat; there may be more

WERROR: MOV DX,Offset WRITXT
OUTMSG: MOV AH,9
PUSH CS
POP DS
INT 21H ; Write error message
MOV AX,4C01H
INT 21H

GOAHEA PROC FAR ; Declare for RET Far at end
MOV AH,40H
MOV BX,1
MOV CX,1CH ; Write exe header template:
XOR DX,DX ; Fill in real values later
INT 21H
JC WERROR
PUSH DS
PUSH Word Ptr CS:[BUFFER+14H] ; Jump to MS exe unpacker
PUSH ES
POP DS ; DS and ES set up as expected
RET ; SS and SP is our stack but
GOAHEA ENDP ; the unpacker doesn't care

WRIREL PROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DS
MOV AX,ES ; Compute real value
SUB AX,Word Ptr CS:[EXEBASE]
PUSH AX ; Save reloc segment value
PUSH DI ; Save reloc offset value
MOV AH,40H
MOV BX,1
MOV CX,4
MOV DX,SP
PUSH SS
POP DS
INT 21H ; Write reloc entry to file
WERRO2: JC WERROR
INC Word Ptr CS:[BUFFER+06H] ; Increment reloc entry count
POP AX
POP AX
POP DS
POP DX
POP CX
POP BX
POP AX
RET
WRIREL ENDP

UNPDON: MOV BP,DS ; Save minimum allocation
LES AX,Dword Ptr DS:[0] ; Get CS:IP
PUSH CS
POP DS ; Restore our DS
MOV Word Ptr DS:[BUFFER+0EH],SI ; Save SS
MOV Word Ptr DS:[BUFFER+10H],DI ; Save SP
MOV Word Ptr DS:[BUFFER+14H],AX ; Save IP
MOV Word Ptr DS:[BUFFER+16H],ES ; Save CS
MOV DX,4
MOV AX,7H
ADD AX,Word Ptr CS:[BUFFER+06H] ; Compute size written so far
MUL DX
MOV CX,AX
NEG CX
AND CH,1 ; Compute needed pad MOD 512
ADD AX,CX ; Compute size after padding
ADC DX,0
SHR DX,1 ; Convert it to paragraphs
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
SHR DX,1
RCR AX,1
PUSH AX
MOV DX,Offset ZERBUF
MOV AH,40H
MOV BX,1
AND CX,CX
JZ NORADJ
INT 21H ; Write pad bytes
JC WERRO2
NORADJ: POP BX
XCHG Word Ptr DS:[BUFFER+08H],BX ; Save padded size, paragraphs
MOV DX,Offset BUFFER ; (BX now image offse, para)
MOV SI,DS
LEA SI,[SI+BX+(Offset BUFFER-Offset START+100H)/10H] ; Image, para
MOV AX,Word Ptr DS:[BUFFER+02H]
DEC AX ; Compute original size
AND AX,1FFH
SHR AX,1
SHR AX,1
SHR AX,1
SHR AX,1
MOV DX,Word Ptr DS:[BUFFER+04H]
SHL DX,1
SHL DX,1
SHL DX,1
SHL DX,1
SHL DX,1
ADD AX,DX
SUB AX,20H-1
SUB AX,BX
MOV DS,SI
NEG SI
LEA SI,[SI+BP]
SUB AX,SI
ADD Word Ptr CS:[BUFFER+0AH],AX ; New min allocation value
CMP Word Ptr CS:[BUFFER+0CH],0FFFFH ; Old max alloc = -1?
JZ ALLMAX
ADD Word Ptr CS:[BUFFER+0CH],AX ; No, compute new max alloc
ALLMAX: MOV AX,SI ; Recompute file size
SHL AL,1
SHL AL,1
SHL AL,1
MOV AH,0
SHL AX,1
MOV Word Ptr CS:[BUFFER+02H],AX ; Save size MOD 512
MOV AX,SI ; Get image size
ADD AX,Word Ptr CS:[BUFFER+08H] ; Get reloc size (= 0 MOD 512)
SHR AX,1
SHR AX,1
SHR AX,1
SHR AX,1
SHR AX,1
TEST SI,1FH ; = 0 MOD 512 ?
JZ EXACBL
INC AX ; No, add overflow "sector"
EXACBL: MOV Word Ptr CS:[BUFFER+04H],AX ; Save "sector" count
WRILOP: MOV CX,SI
SHL CX,1
SHL CX,1
SHL CX,1
SHL CX,1
SUB SI,0F80H
JB WRILEX
MOV CX,0F800H
WRILEX: MOV AH,40H ; Write all of image
MOV BX,1
XOR DX,DX
INT 21H
JC WERRO3
MOV AX,DS
ADD AX,0F80H
MOV DS,AX
CMP SI,0F000H
JB WRILOP

MOV AX,4200H ; Seek to beginning of file
MOV BX,1
XOR CX,CX
XOR DX,DX
INT 21H
JC WERRO3
PUSH CS
POP DS
MOV AH,40H ; Write updated exe header
MOV BX,1
MOV CX,1CH
MOV Word Ptr DS:[BUFFER+18H],CX ; Fill in start of reloc table
MOV DX,Offset BUFFER
GOOEXI: INT 21H
MOV AX,4C00H
JNC GOOEXI
WERRO3: JMP WERROR

NOPTXT DB "File is not EXEpacked$"
TOOTXT DB "Out of memory$"
WRITXT DB "Write error$"
REATXT DB "Read error$"

EXEBASE Label Word

ZERBUF EQU EXEBASE+2

ORG ZERBUF+1FCH-300H
BUFALI:
ORG $+((Offset START-Offset BUFALI) AND 15)

BUFFER EQU $+300H

CODE ENDS
END START


  3 Responses to “Category : Assembly Language Source Code
Archive   : UNEXEP10.ZIP
Filename : UNEXEPAC.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/