This is an old revision of the document!
WindowsDLLs
----
+ Checkout(file)
- Checkin(file)
-----------------------------------------------
NetMD.dll COM (AVLib) c++ code
-----------------------------------------------
| |
| v (This equivalent functionality as libnetmd)
| ----------------------------------
| NetMDAPI.dll / NetMDUSB.sys c++ code
| -----------------------------------
+ IOmgNetMD::AttemptCheckout, CompleteCheckout...
|
---------------------------------------------- COM
OmgNetMD.dll c++ code
-----------------------------------------------
|
| salExec0 ( A procedure in netmd.ocm would implement first step in checkout...)
|---------------------------------------------------------- netmd.ocm (encrypted bytecode and c code)
|
---------------------------------------------- DLL
salwrap.dll c++ code
--------------------------------
Application VM
-------------------------------- <--------------- init.ocm (interpeter, and runtime c libraries)
----------------------------------------------
Virtual Machine overview
---------------------------------- OpenMG Module ---------------------------------- | ---------------------------------- ocm_module_proc_X() ---------------------------------- | salExec0 ............................................................... Secure Application Loader ............................................................... | ---------------------------------- Secure Application ---------------------------------- ^ | v ---------------------------------- Virtual ISA + Virtual ABI (library calls.) virtual machine ---------------------------------- ISA salwrap (host) ---------------------------------- ISA + ABI Windows ---------------------------------- ISA Hardware ---------------------------------- * ISA: Instruction Set Architecture. * Virtual ISA: bytecode architecture. * ABI: Application Binary Interface: Interface to OS System Calls. * Virtual ISA: library calls to runtime libraries.
C++ interface to the virtual machine (application loader)
#include <iostream>
#include <vector>
using namespace std;
class SalBytecode
{
SalBytecode(unsigned int);
clear();
dataType();
SalBytecode & operator=(class SalBytecode const &);
~SalBytecode();
// Input stream operators
operator<<(SalBytecode &, long &);
operator<<(SalBytecode &, SalPointer const &);
operator<<(SalBytecode &, SalNonConstPointer const &);
operator<<(SalBytecode &, OmgString const &);
operator<<(SalBytecode &, SalString const &);
operator<<(SalBytecode &, SalFileContent const &);
operator<<(SalBytecode &, SalExtrinsicsProg const &);
operator<<(SalBytecode &, SalLoadableModule const &);
operator<<(SalBytecode &, std::vector<unsigned char> &)
operator<<(SalBytecode &, SalOmgId const &);
operator<<(SalBytecode &, OmgMmap const &);
operator<<(SalBytecode &, SalKey const &);
// Output stream operators
operator>>(SalBytecode &, std::string<char> &);
operator>>(SalBytecode &, std::vector<unsigned char> &);
operator>>(SalBytecode &, SalAsnSeqBegin);
operator>>(SalBytecode &, SalAsnSeqEnd &);
operator>>(SalBytecode &, SalNonConstPointer &);
operator>>(SalBytecode &, OmgString &);
private:
SalBytecode::SalByteCode_impl_constr(var_size_512);
// 10 vars
// var 0
uchar *StreamBuf; // var 1
int StreamPos; // var 2
long int lenStreamBuf; // var 3h
int inArgSize; // var10: 512
};
void salExec0(SalBytecode& input, SalBytecode& output, int, int, int);
The ocm-files
OCM-Interpretor:
- http://users.physik.fu-berlin.de/~glaubitz/linux-minidisc/dis-09-02-01.rar - latest version as of May, 2nd 2009
The OCM files (except for init.ocm which contains an extra layer of packing) are interpreted as OCMBytecode
Here is a decode for native code blocks from OCM files. It is severe works-for-me-quality, having at least the following issues:
- It does not name imports from salwrap, it just puts offsets into the import table into a generic name. Check here for some name OCMSalwrapExports
- It is unable to parse named exports
- It does only support the relocation types (mostly direct imports of compiler helper functions) I needed.
The output of the program is an assembler source file (completely unreadable) that is intended to be compiled by the GNU assembler (Win32 port or cross-assembler in linux) and then loaded into a good disassembler, like IDA 4.9 Freeware for example.
Some info about analysing an OCM file can be found in this part of chat log:
These new pages could be created (internal access only)
Start for device.sal (arguments as on stack, last one top of stack):
int
dev_0x01 (blob_t someblob, bool_t somebool)
{
int res;
if (somebool == 1)
{
res = dev_0x00 (someblob);
if (res != 0)
return res;
}
int some_nr = (unsigned) SubBlob (someblob, 0, 4);
int some_nr2 = (unsigned) dev_0xd1 (some_nr);
res = "localekb" (some_nr2);
// FIXME: Don't know the stack layout after this.
if (res != 0)
return; // but what?
blob_t someblob2; // probably from localekb
int some_nr3 = (signed) SubBlob (someblob2, 0, 4) + 1;
vector<blob_t> vec;
do
{
vec.append (SubBlob (some_nr3 * 16, 24));
}
while (some_nr3-- >= 0);
int some_nr3 = (signed) SubBlob (someblob2, 0, 4);
res = dev_0xc1 (some_nr3);
if (res != 0)
return res;
int some_nr4 = (signed) SubBlob (someblob2, 16, 4);
if (some_nr3 == some_nr4)
return 0;
else
return 8;
// is vec returned as well? it's still on the stack.
}
int
dev_0xb7 (any_t thing)
{
if (get_type (thing) != TYPE_BLOB)
return 0;
if (thing[2] == 0x31)
return 2;
else
{
if (! strncmp (thing, "\x31\x31", 2))
return 1;
else
return 0;
}
}
block_t
dev_0xd1 (int nr)
{
if (nr > 1)
{
0x80 ("Invalid version...");
return 0;
}
else
{
return 00 81 00 00 00 00 00 00;
}
}
// Some decrypt function.
any_t
dev_0xd8 (blob_t data1, blob_t data2)
{
blob_t data3 = data2 XOR concat (dict[0xfc], dict[0xfc]);
dict[0xdb] = data3;
blob_t shasum = SHA1 (data3[0..1f]);
blob_t iv = shasum[0..7];
blob_t key = shasum[8..15]
blob_t dec_data1 = DES_CBC_Decrypt (data1, iv, key, 0xd8_DESDecrypt);
int len = blob_length (dec_data);
// Round up to multiple of 8.
len = (len + 7) / 8 * 8;
blob_t out = repeat_nul (len);
// Modifies OUT. 1 means that length is provided.
out = native::ocmmod (dec_data1, out, shasum, len, 1);
return decode_asn1 (out);
}
// Do something. // If use_len is TRUE, the provided LEN parameter is used, otherwise LEN is determined // from DATA. Modifies OUT and returns it. blob_t native::ocmmod (blob_t data, blob_t out, blob_t shasum, int len, bool_t use_len);
