Update of /cvsroot/openantivirus/java/src/org/openantivirus/engine/vfs/container/ucl
In directory sc8-pr-cvs1:/tmp/cvs-serv4777/java/src/org/openantivirus/engine/vfs/container/ucl
Added Files:
EXEHeader.java PackHeader.java PESection.java CStructure.java
PEHeader.java UPXDecompress.java
Log Message:
Rewrite of the engine to use a virtual file system
Move to 'engine' subdirectory
Added bzip2 and tar decompressors
Switch from GPL to MPL
--- NEW FILE: EXEHeader.java ---
/*
* $Id: EXEHeader.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OAV.
*
* The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
* Portions created by the Initial Developer are Copyright (C) 2001-2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package org.openantivirus.engine.vfs.container.ucl;
/**
* EXEHeader
*
* Pattern-Roles:
* @author Kurt Huwig <[email protected]>
* @version $Revision: 1.1 $
*/
public class EXEHeader extends CStructure {
public static final String VERSION =
"$Id: EXEHeader.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
public static final int SIZE = 64;
/** Offsets */
private static final int
MZ = 0,
M512 = 2,
P512 = 4,
RELOCATION_OFFSET = 24,
NEXT_E_POSITION = 60;
public EXEHeader(byte[] data) {
super(data, SIZE);
}
public int getMZ() {
return getLE16(MZ);
}
public int getM512() {
return getLE16(M512);
}
public int getP512() {
return getLE16(P512);
}
public int getRelocationOffset() {
return getLE16(RELOCATION_OFFSET);
}
public long getNextEPos() {
return getLE32(NEXT_E_POSITION);
}
}
--- NEW FILE: PackHeader.java ---
/*
* $Id: PackHeader.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OAV.
*
* The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
* Portions created by the Initial Developer are Copyright (C) 2001-2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package org.openantivirus.engine.vfs.container.ucl;
/**
* PackHeader
*
* Pattern-Roles:
* @author Kurt Huwig <[email protected]>
* @version $Revision: 1.1 $
*/
public class PackHeader {
public static final String VERSION =
"$Id: PackHeader.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
private static final byte[] UPX_MAGIC_LE32 = {'U', 'P', 'X', '!'};
private static final int
UPX_F_DOS_COM = 1,
UPX_F_DOS_SYS = 2,
UPX_F_DOS_EXE = 3,
UPX_F_DOS_EXEH = 7;
private int version;
private int format;
private int method;
private int level;
private int filter;
private int filter_cto;
private long u_adler, c_adler;
private int u_len, c_len;
private int u_file_size;
private int buf_offset;
public boolean fillPackHeader(byte[] data) {
int l = find(data, UPX_MAGIC_LE32);
if (l == -1) {
return false;
}
buf_offset = l;
version = CStructure.getByte(data, l + 4);
format = CStructure.getByte(data, l + 5);
method = CStructure.getByte(data, l + 6);
level = CStructure.getByte(data, l + 7);
filter_cto = 0;
int off_filter = 0;
if (format < 128) {
u_adler = CStructure.getLE32(data, l + 8);
c_adler = CStructure.getLE32(data, l + 12);
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) {
u_len = CStructure.getLE16(data, l + 16);
c_len = CStructure.getLE16(data, l + 18);
u_file_size = u_len;
off_filter = 20;
} else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) {
u_len = CStructure.getLE24(data, l + 16);
c_len = CStructure.getLE24(data, l + 19);
u_file_size = CStructure.getLE24(data, l + 22);
off_filter = 25;
} else {
u_len = (int) CStructure.getLE32(data, l + 16);
c_len = (int) CStructure.getLE32(data, l + 20);
u_file_size = (int) CStructure.getLE32(data, l + 24);
off_filter = 28;
filter_cto = CStructure.getByte(data, l + 29);
}
} else {
u_len = (int) CStructure.getBE32(data, l + 8);
c_len = (int) CStructure.getBE32(data, l + 12);
u_adler = CStructure.getBE32(data, l + 16);
c_adler = CStructure.getBE32(data, l + 20);
u_file_size = (int) CStructure.getBE32(data, l + 24);
off_filter = 28;
filter_cto = CStructure.getByte(data, l + 29);
}
if (version >= 10) {
filter = CStructure.getByte(data, l + off_filter);
} else if ((level & 128) == 0) {
filter = 0;
} else {
level &= 0x7f;
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) {
filter = 0x06;
} else {
filter = 0x26;
}
}
level &= 0x0f;
return true;
}
public boolean checkPackHeader(byte[] data) {
if (version == 0xff) {
System.out.println("cannot unpack UPX ;-)");
return false;
}
final int hs = getPackHeaderSize();
final int hlen = data.length - buf_offset;
if (hlen <= 0 || hs > hlen) {
System.err.println("header corrupted");
return false;
}
if (version > 9) {
if (data[buf_offset + hs - 1]
!= getPackHeaderChecksum(data, hs - 1)) {
System.err.println("header corrupted");
return false;
}
}
return true;
}
public int getVersion() {
return version;
}
public int getCLength() {
return c_len;
}
public int getULength() {
return u_len;
}
public int getMethod() {
return method;
}
public int getBufferOffset() {
return buf_offset;
}
protected byte getPackHeaderChecksum(byte[] data, int len) {
int buf = buf_offset;
buf += 4;
len -= 4;
int c = 0;
while (len-- > 0) {
c += CStructure.getByte(data, buf++);
}
c %= 251;
return (byte) c;
}
protected int getPackHeaderSize() {
int n = 0;
if (version <= 3) {
n = 24;
} else if (version <= 9) {
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) {
n = 20;
} else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) {
n = 25;
} else {
n = 28;
}
} else {
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS) {
n = 22;
} else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH) {
n = 27;
} else {
n = 32;
}
}
if (n == 0) {
System.err.println("unknown header version");
}
return n;
}
protected int find(byte[] data, byte[] pattern) {
ldata: for (int i = 0; i < data.length; i++) {
for (int j = 0; j < pattern.length; j++) {
if (data[i + j] != pattern[j]) {
continue ldata;
}
}
return i;
}
return -1;
}
}
--- NEW FILE: PESection.java ---
/*
* $Id: PESection.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OAV.
*
* The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
* Portions created by the Initial Developer are Copyright (C) 2001-2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package org.openantivirus.engine.vfs.container.ucl;
/**
* Section of a PE file
*
* Pattern-Roles:
* @author Kurt Huwig <[email protected]>
* @version $Revision: 1.1 $
*/
public class PESection extends CStructure {
public static final String VERSION =
"$Id: PESection.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
public static final int SIZE = 40;
/** Offsets */
private static final int
VADDRESS = 12,
RAW_DATA_POINTER = 20;
/** Maximum length of section name */
private static final int MAX_NAME_LENGTH = 8;
public PESection(byte[] data) {
super(data, SIZE);
}
public long getVAddress() {
return getLE32(VADDRESS);
}
public String getName() {
final StringBuffer sb = new StringBuffer();
for (int i = 0; i < MAX_NAME_LENGTH; i++) {
final int value = getByte(i);
if (value == 0) {
break;
}
sb.append((char) value);
}
return sb.toString();
}
public long getRawDataPointer() {
return getLE32(RAW_DATA_POINTER);
}
}
--- NEW FILE: CStructure.java ---
/*
* $Id: CStructure.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OAV.
*
* The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
* Portions created by the Initial Developer are Copyright (C) 2001-2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package org.openantivirus.engine.vfs.container.ucl;
/**
* Wrapper to decode a C 'struct'
*
* Pattern-Roles:
* @author Kurt Huwig <[email protected]>
* @version $Revision: 1.1 $
*/
public class CStructure {
public static final String VERSION =
"$Id: CStructure.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
private final byte[] data;
public CStructure(byte[] data, int size) {
this.data = data;
if (data.length != size) {
throw new IllegalArgumentException("Datasize must be "
+ size);
}
}
public int getByte(int index) {
return getByte(data, index);
}
public int getLE16(int index) {
return getLE16(data, index);
}
public long getLE32(int index) {
return getLE32(data, index);
}
public static int getByte(byte[] data, int index) {
return ((data[index] + 256) & 0xff);
}
public static int getLE16(byte[] data, int index) {
return (getByte(data, index) | (getByte(data, index + 1) << 8));
}
public static int getBE16(byte[] data, int index) {
return (getByte(data, index + 1) | (getByte(data, index) << 8));
}
public static int getLE24(byte[] data, int index) {
return ((int) getLE16(data, index)
+ (((int) getByte(data, index + 2)) << 16));
}
public static long getLE32(byte[] data, int index) {
return ((long) getLE16(data, index)
+ (((long) getLE16(data, index + 2)) << 16));
}
public static long getBE32(byte[] data, int index) {
return ((long) getBE16(data, index + 2)
+ (((long) getBE16(data, index)) << 16));
}
}
--- NEW FILE: PEHeader.java ---
/*
* $Id: PEHeader.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OAV.
*
* The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
* Portions created by the Initial Developer are Copyright (C) 2001-2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package org.openantivirus.engine.vfs.container.ucl;
/**
* Header of a PE file
*
* Pattern-Roles:
* @author Kurt Huwig <[email protected]>
* @version $Revision: 1.1 $
*/
public class PEHeader extends CStructure {
public static final String VERSION =
"$Id: PEHeader.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
public static final int SIZE = 248;
/** Offsets */
private static final int
OBJECTS = 6,
ENTRY = 40,
DDIRS_START = 120,
DDIRS_LENGTH = 8,
DDIRS_VADDR = 0,
DDIRS_SIZE = 4;
public PEHeader(byte[] data) {
super(data, SIZE);
}
public int getObjects() {
return getLE16(OBJECTS);
}
public long getEntry() {
return getLE32(ENTRY);
}
public long getDDirsSize(int index) {
return getLE32(DDIRS_START + DDIRS_LENGTH * index + DDIRS_SIZE);
}
}
--- NEW FILE: UPXDecompress.java ---
/*
* $Id: UPXDecompress.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is OAV.
*
* The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
* Portions created by the Initial Developer are Copyright (C) 2001-2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
package org.openantivirus.engine.vfs.container.ucl;
import java.io.*;
/**
* Decompresses upx compressed files
*
* Pattern-Roles:
* @author Kurt Huwig <[email protected]>
* @version $Revision: 1.1 $
*/
public class UPXDecompress {
private final RandomAccessFile raf;
private final long file_size;
/** Creates a new instance of UPXDecompress */
public UPXDecompress(RandomAccessFile raf, long file_size) {
this.raf = raf;
this.file_size = file_size;
}
private static final int MAX_IC = 20;
private static final String UPX_SECTION_NAME = "UPX";
private static final int MAX_VERSION = 12;
private static final int
M_NRV2B_LE32 = 2,
M_NRV2B_8 = 3,
M_NRV2B_LE16 = 4,
M_NRV2D_LE32 = 5,
M_NRV2D_8 = 6,
M_NRV2D_LE16 = 7;
private boolean isRTM;
private long pe_offset;
private PEHeader ih;
private PESection[] isection;
private final PackHeader ph = new PackHeader();
public boolean canUnpack() throws IOException {
if (!readFileHeader()) {
return false;
}
int objects = ih.getObjects();
if (objects != 3) {
return false;
}
isection = new PESection[objects];
raf.seek(pe_offset + PEHeader.SIZE);
for (int i = 0; i < isection.length; i++) {
final byte[] data = new byte[PESection.SIZE];
raf.readFully(data);
isection[i] = new PESection(data);
}
if (((ih.getDDirsSize(15) == 0)
&& !(ih.getEntry() > isection[1].getVAddress()))) {
return false;
}
if (isection[0].getName().startsWith(UPX_SECTION_NAME)) {
return (readPackHeader(1024, isection[1].getRawDataPointer() - 64)
|| readPackHeader(1024, isection[2].getRawDataPointer()));
}
return false;
}
protected boolean readPackHeader(int len, long seek_offset)
throws IOException {
if (len <= 0 || seek_offset < 0) {
return false;
}
final byte[] buf = new byte[len];
raf.seek(seek_offset);
raf.readFully(buf);
if (!ph.fillPackHeader(buf)) {
return false;
}
if (!ph.checkPackHeader(buf)) {
return false;
}
if (ph.getVersion() > MAX_VERSION) {
throw new IOException("need a newer version of UPX");
}
if (ph.getCLength() >= ph.getULength()
|| ph.getCLength() >= file_size) {
throw new IOException("header corrupted");
}
if (ph.getMethod() < M_NRV2B_LE32 || ph.getMethod() > M_NRV2D_LE16) {
throw new IOException("unknown compression method");
}
return true;
}
protected boolean readFileHeader() throws IOException {
EXEHeader h;
pe_offset = 0;
int ic;
for (ic = 0; ic < MAX_IC; ic++) {
raf.seek(pe_offset);
final byte[] data = new byte[EXEHeader.SIZE];
raf.readFully(data);
h = new EXEHeader(data);
if (h.getMZ() == ('M' | ('Z' << 8))) { // DOS exe
if (h.getRelocationOffset() >= 0x40) { // new format exe
pe_offset += h.getNextEPos();
} else {
pe_offset += (h.getP512() << 9) + h.getM512()
- (h.getM512() != 0 ? 512 : 0);
}
} else if (h.getLE32(0) == ('P' | ('E' << 8))) {
break;
} else {
return false;
}
}
if (ic == 20) {
return false;
}
final byte[] data = new byte[PEHeader.SIZE];
raf.seek(pe_offset);
raf.readFully(data);
ih = new PEHeader(data);
final String sStub = "32STUB";
final byte[] aStub = new byte[sStub.length()];
raf.seek(0x200);
raf.readFully(aStub);
isRTM = sStub.equals(new String(aStub));
return true;
}
private int ilen;
private byte[] src, dst;
public void decompress(OutputStream os) throws IOException {
if (ih == null) {
throw new IllegalStateException("Need to call 'canUnpack()' first");
}
raf.seek(isection[1].getRawDataPointer() - 64 + ph.getBufferOffset()
+ ph.getPackHeaderSize());
src = new byte[ph.getCLength()];
raf.readFully(src);
dst = new byte[ph.getULength()];
bitBuffer = 0;
bitCount = 0;
ilen = 0;
int olen = 0, last_m_off = 1;
while (true) {
while (getbit() != 0) {
dst[olen++] = src[ilen++];
}
long m_off = 1;
do {
m_off = (m_off << 1) + getbit();
} while (getbit() == 0);
if (m_off == 2) {
m_off = last_m_off;
} else {
m_off = ((m_off - 3) << 8) + CStructure.getByte(src, ilen++);
if (m_off == 0xffffffffL) {
break;
}
last_m_off = (int) ++m_off;
}
int m_len = getbit();
m_len = (m_len << 1) + getbit();
if (m_len == 0) {
m_len++;
do {
m_len = (m_len << 1) + getbit();
} while (getbit() == 0);
m_len += 2;
}
m_len += (m_off > 0xd00) ? 1 : 0;
int m_pos = (int) (olen - m_off);
dst[olen++] = dst[m_pos++];
do {
dst[olen++] = dst[m_pos++];
} while (--m_len > 0);
}
if (os != null) {
os.write(dst);
}
if (ilen < src.length) {
throw new IOException("UPX input not consumed");
}
}
private long bitBuffer;
private int bitCount;
protected int getbit() throws IOException {
if (bitCount > 0) {
bitCount--;
return (int) ((bitBuffer >> bitCount) & 1);
} else {
bitCount = 31;
bitBuffer = CStructure.getByte(src, ilen++)
+ (CStructure.getByte(src, ilen++) << 8)
+ (CStructure.getByte(src, ilen++) << 16)
+ (CStructure.getByte(src, ilen++) << 24);
return (int) ((bitBuffer >> 31) & 1);
}
}
public void close() throws IOException {
raf.close();
}
}
-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive? Does it
help you create better code? SHARE THE LOVE, and help us help
YOU! Click Here: http://sourceforge.net/donate/
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.