Код HTML:
#include <windows.h>
#include "..\\dtr.hpp"
class BBStream
{
private:
BYTE* base;
BYTE* p;
int idx;
int len;
bool eof;
WORD bits;
public:
BBStream(BYTE* from, int blockSize)
{
base = p = from;
len = blockSize;
idx = 0;
eof = false;
bits = getByte();
bits += 256*getByte();
}
BYTE getByte(void)
{
if(p - base == len) { eof = true; return 0; }
return *p++;
}
BYTE getBit()
{
WORD mask[] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
BYTE bit = (bits & mask[idx]) ? 1 : 0;
if(idx == 15)
{
bits = getByte();
bits += 256*getByte();
}
idx = (idx + 1) % 16;
return bit;
}
BYTE getBits(int n)
{
BYTE r = 0;
do { r = 2*r + getBit(); } while(--n);
return r;
}
bool error(void) { return eof; }
};
bool WINAPI extract(HoHdr *hdr, const BYTE *source, DWORD, BYTE *unpackBuffer, DWORD *noUnpackedBytes, DWORD)
{
BYTE *from = (BYTE*)source;
BYTE *to = unpackBuffer;
if(source[0] != 'H' || source[1] != 'R')
from += 0x103;
BBStream s(from + 12, from[4] + 256*from[5]);
*to++ = s.getByte();
BYTE noBits = 2;
BYTE mask[] = { 0, 0, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0 };
while(!s.error())
{
while(s.getBit()) *to++ = s.getByte();
WORD len = 0;
BYTE bb = 0;
do
{
bb = s.getBits(2);
len += bb;
} while(bb == 0x03 && len != 0x0f);
short offset = 0;
if(len == 0)
{
offset = 0xfff8 + s.getBits(3);
*to++ = to[offset];
continue;
}
if(len == 1)
{
BYTE code = s.getBits(2);
if(code == 2)
{
BYTE b = s.getByte();
if(b >= 0xe0)
{
b <<= 1; ++b; // rlca
b ^= 2; // xor c
if(b == 0xff) { ++noBits; continue; }
offset = 0xff00 + b - 0x0f;
*to++ = to[offset];
*to++ = s.getByte();
*to++ = to[offset];
continue;
}
offset = 0xff00 + b;
}
if(code == 0 || code == 1)
{
offset = s.getByte();
offset += 256*(code ? 0xfe : 0xfd);
}
if(code == 3) offset = 0xffe0 + s.getBits(5);
for(BYTE i = 0; i < 2; ++i)
*to++ = to[offset];
continue;
}
if(len == 3)
{
if(s.getBit())
{
offset = 0xfff0 + s.getBits(4);
*to++ = to[offset];
*to++ = s.getByte();
*to++ = to[offset];
continue;
}
if(s.getBit())
{
BYTE noBytes = 6 + s.getBits(4);
for(BYTE i = 0; i < 2*noBytes; ++i)
*to++ = s.getByte();
continue;
}
len = s.getBits(7);
if(len == 0x0f) break; // EOF
if(len < 0x0f) len = 256*len + s.getByte();
}
if(len == 2) ++len;
BYTE code = s.getBits(2);
if(code == 1)
{
BYTE b = s.getByte();
if(b >= 0xe0)
{
if(len > 3) return false;
b <<= 1; ++b; // rlca
b ^= 3; // xor c
offset = 0xff00 + b - 0x0f;
*to++ = to[offset];
*to++ = s.getByte();
*to++ = to[offset];
continue;
}
offset = 0xff00 + b;
}
if(code == 0) offset = 0xfe00 + s.getByte();
if(code == 2) offset = 0xffe0 + s.getBits(5);
if(code == 3)
{
offset = 256*(mask[noBits] + s.getBits(noBits));
offset += s.getByte();
}
for(WORD i = 0; i < len; ++i)
*to++ = to[offset];
}
for(int i = 0; i < 6; ++i)
*to++ = from[6+i];
*noUnpackedBytes = to-unpackBuffer;
return true;
}
bool WINAPI detect(DetectorResult &result, const char*, const HoHdr*, const BYTE *data, int file_size)
{
WORD size;
WORD packed_size;
while(true)
{
if(data[0] == 'H' && data[1] == 'R')
{
size = *(WORD*)(data + 2);
packed_size = *(WORD*)(data + 4);
// check for HRiP
if(data[2] == 'i' && (data[2+5] == 0 || data[2+5] == 1))
return false;
break;
}
if(data[0x103] == 'H' && data[0x104] == 'R')
{
size = *(WORD*)(data + 0x105);
packed_size = *(WORD*)(data + 0x107);
break;
}
return false;
}
if(packed_size > size || packed_size > file_size)
return false;
result.action = do_extract;
lstrcpy(result.title, "[hrust 1.x]");
return true;
}
Код HTML:
#include "stdafx.h"
#include "hrust1.h"
#include <vector>
class BBStream
{
private:
BYTE* base;
BYTE* p;
int idx;
int len;
bool eof;
WORD bits;
public:
BBStream(BYTE* from, int blockSize)
{
base = p = from;
len = blockSize;
idx = 0;
eof = false;
bits = getByte();
bits += 256*getByte();
}
BYTE getByte(void)
{
if(p - base == len) { eof = true; return 0; }
return *p++;
}
BYTE getBit()
{
WORD mask[] = { 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
BYTE bit = (bits & mask[idx]) ? 1 : 0;
if(idx == 15)
{
bits = getByte();
bits += 256*getByte();
}
idx = (idx + 1) % 16;
return bit;
}
BYTE getBits(int n)
{
BYTE r = 0;
do { r = 2*r + getBit(); } while(--n);
return r;
}
bool error(void) { return eof; }
};
extern "C" HRUST1_API void *hrust1_extract(const BYTE *source, DWORD *noUnpackedBytes)
{
WORD packed_size;
BYTE *from = (BYTE*)source;
BYTE *unpackBuffer = 0;
*noUnpackedBytes = 0;
std::vector<BYTE> out;
try
{
if(source[0] != 'H' || source[1] != 'R')
from += 0x103;
BBStream s(from + 12, from[4] + 256*from[5]);
out.push_back(s.getByte());
BYTE noBits = 2;
BYTE mask[] = { 0, 0, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0 };
while(!s.error())
{
while(s.getBit())
{
out.push_back(s.getByte());
}
WORD len = 0;
BYTE bb = 0;
do
{
bb = s.getBits(2);
len += bb;
} while(bb == 0x03 && len != 0x0f);
short offset = 0;
if(len == 0)
{
offset = 0xfff8 + s.getBits(3);
out.push_back(out.at(out.size() + offset));
continue;
}
if(len == 1)
{
BYTE code = s.getBits(2);
if(code == 2)
{
BYTE b = s.getByte();
if(b >= 0xe0)
{
b <<= 1; ++b; // rlca
b ^= 2; // xor c
if(b == 0xff) { ++noBits; continue; }
offset = 0xff00 + b - 0x0f;
out.push_back(out.at(out.size() + offset));
out.push_back(s.getByte());
out.push_back(out.at(out.size() + offset));
continue;
}
offset = 0xff00 + b;
}
if(code == 0 || code == 1)
{
offset = s.getByte();
offset += 256*(code ? 0xfe : 0xfd);
}
if(code == 3) offset = 0xffe0 + s.getBits(5);
for(BYTE i = 0; i < 2; ++i)
out.push_back(out.at(out.size() + offset));
continue;
}
if(len == 3)
{
if(s.getBit())
{
offset = 0xfff0 + s.getBits(4);
out.push_back(out.at(out.size() + offset));
out.push_back(s.getByte());
out.push_back(out.at(out.size() + offset));
continue;
}
if(s.getBit())
{
BYTE noBytes = 6 + s.getBits(4);
for(BYTE i = 0; i < 2*noBytes; ++i)
out.push_back(s.getByte());
continue;
}
len = s.getBits(7);
if(len == 0x0f) break; // EOF
if(len < 0x0f) len = 256*len + s.getByte();
}
if(len == 2) ++len;
BYTE code = s.getBits(2);
if(code == 1)
{
BYTE b = s.getByte();
if(b >= 0xe0)
{
if(len > 3) return false;
b <<= 1; ++b; // rlca
b ^= 3; // xor c
offset = 0xff00 + b - 0x0f;
out.push_back(out.at(out.size() + offset));
out.push_back(s.getByte());
out.push_back(out.at(out.size() + offset));
continue;
}
offset = 0xff00 + b;
}
if(code == 0) offset = 0xfe00 + s.getByte();
if(code == 2) offset = 0xffe0 + s.getBits(5);
if(code == 3)
{
offset = 256*(mask[noBits] + s.getBits(noBits));
offset += s.getByte();
}
for(WORD i = 0; i < len; ++i)
out.push_back(out.at(out.size() + offset));
}
for(int i = 0; i < 6; ++i)
out.push_back(from[6+i]);
}
catch(...)
{
return 0;
}
*noUnpackedBytes = out.size();
unpackBuffer = (BYTE *)malloc(*noUnpackedBytes);
std::vector<BYTE>::pointer ptr = &out [0];
memcpy(unpackBuffer, ptr, *noUnpackedBytes);
return unpackBuffer;
}
extern "C" HRUST1_API int hrust1_detect(const BYTE *data)
{
WORD size;
WORD packed_size;
while(true)
{
if(data[0] == 'H' && data[1] == 'R')
{
size = *(WORD*)(data + 2);
packed_size = *(WORD*)(data + 4);
// check for HRiP
if(data[2] == 'i' && (data[2+5] == 0 || data[2+5] == 1))
return 0;
break;
}
return 0;
}
if(packed_size > size)
return 0;
return size;
}