#include #include #include #include #include "debug.h" #include "stringutils.h" #include "asn1decode.h" #include "vectorutils.h" #include "err/posix.h" #include struct security_attribute { uint32_t size; uint16_t version; uint16_t type; }; typedef boost::shared_ptr file_ptr; template void fileread(file_ptr f, size_t offset, T& item) { if (-1==fseek(f.get(), (long)offset, SEEK_SET)) throw "fseek"; if (1!=fread(&item, sizeof(item), 1, f.get())) throw "fread"; } bool GetFileSignature(const std::string& filename, ByteVector& sig, uint16_t& version, uint16_t& type, uint32_t& offset) { file_ptr f= file_ptr(fopen(filename.c_str(), "rb"), fclose); if (f==NULL) throw posixerror("fopen"); uint16_t mzmagic; fileread(f, 0, mzmagic); if (mzmagic!=0x5a4d) return false; uint32_t lfanew; fileread(f, 0x3c, lfanew); uint32_t pemagic; fileread(f, lfanew, pemagic); if (pemagic!=0x4550) return false; uint16_t opthdrmagic; fileread(f, lfanew+0x18, opthdrmagic); if (opthdrmagic!=0x010b) return false; uint32_t secinfo[2]; fileread(f, lfanew+0x98, secinfo); if (secinfo[0]==0 && secinfo[1]==0) return false; security_attribute attr; fileread(f, secinfo[0], attr); sig.resize(attr.size-8); if (1!=fread(&sig[0], attr.size-8, 1, f.get())) { printf("error reading exe SEC: @%08x:l=%x : attr %04x/%04x/%08x %s\n", secinfo[0], secinfo[1], attr.version, attr.type, attr.size, filename.c_str()); throw posixerror("fread(cert)"); } version= attr.version; type= attr.type; offset= secinfo[0]+8; return true; } bool FindCertificate(const std::string& filename, ByteVector& cert) { uint16_t version; uint16_t type; uint32_t offset; ByteVector sig; try { if (!GetFileSignature(filename, sig, version, type, offset)) return false; } catch (const char*msg) { if (std::string(msg)!="no exe") debug("ERROR: %s\n", msg); return false; } debug("@%08x: version=%04x, type=%04x\n", offset, version, type); //debug("sig: %s\n", vhexdump(sig).c_str()); const char certnode[]= { 0,-1,0,-1 }; ByteVector::iterator a0, a1; if (decodeasn1(sig.begin(), sig.end(), certnode+(version==0x100?2:0), certnode+sizeof(certnode)/sizeof(*certnode), a0, a1)) { cert.resize((unsigned)(a1-a0)); std::copy(a0, a1, cert.begin()); return true; } return false; }