//golang实现读取exedllapk版本号 packagemain import( "flag" "fmt" "log" "os" "path/filepath" ) import( "github.com/lunny/axmlParser" ) var( filefileInfo ) const( MZ="MZ" PE="PE" RSRC=".rsrc" TYPET=16 PEOFFSET=64 MACHINE=332 DEFAULT=`C:\Windows\System32\cmd.exe` ) typefileInfostruct{ FilePathstring Versionstring Debugbool } func(f*fileInfo)checkError(errerror){ iferr!=nil{ log.Fatalln(err) } } //获取exedll版本 func(f*fileInfo)GetExeVersion()(errerror){ file,err:=os.Open(f.FilePath) f.checkError(err) //第一次读取64byte buffer:=make([]byte,64) _,err=file.Read(buffer) f.checkError(err) deferfile.Close() str:=string(buffer[0])+string(buffer[1]) ifstr!=MZ{ log.Fatalln("读取exe错误,找不到MZ.",f.FilePath) } peOffset:=f.unpack([]byte{buffer[60],buffer[61],buffer[62],buffer[63]}) ifpeOffset<PEOFFSET{ log.Fatalln("peOffset读取错误.",f.FilePath) } //读取从文件开头移位到peOffset,第二次读取24byte _,err=file.Seek(int64(peOffset),0) buffer=make([]byte,24) _,err=file.Read(buffer) f.checkError(err) str=string(buffer[0])+string(buffer[1]) ifstr!=PE{ log.Fatalln("读取exe错误,找不到PE.",f.FilePath) } machine:=f.unpack([]byte{buffer[4],buffer[5]}) ifmachine!=MACHINE{ log.Fatalln("machine读取错误.",f.FilePath) } noSections:=f.unpack([]byte{buffer[6],buffer[7]}) optHdrSize:=f.unpack([]byte{buffer[20],buffer[21]}) //读取从当前位置移位到optHdrSize,第三次读取40byte file.Seek(int64(optHdrSize),1) resFound:=false fori:=0;i<int(noSections);i++{ buffer=make([]byte,40) file.Read(buffer) str=string(buffer[0])+string(buffer[1])+string(buffer[2])+string(buffer[3])+string(buffer[4]) ifstr==RSRC{ resFound=true break } } if!resFound{ log.Fatalln("读取exe错误,找不到.rsrc.",f.FilePath) } infoVirt:=f.unpack([]byte{buffer[12],buffer[13],buffer[14],buffer[15]}) infoSize:=f.unpack([]byte{buffer[16],buffer[17],buffer[18],buffer[19]}) infoOff:=f.unpack([]byte{buffer[20],buffer[21],buffer[22],buffer[23]}) //读取从文件开头位置移位到infoOff,第四次读取infoSizebyte file.Seek(int64(infoOff),infoSize) _,err=file.Read(buffer) f.checkError(err) nameEntries:=f.unpack([]byte{buffer[12],buffer[13]}) idEntries:=f.unpack([]byte{buffer[14],buffer[15]}) varinfoFoundbool varsubOff,iint64 fori=0;i<(nameEntries+idEntries);i++{ typeT:=f.unpack([]byte{buffer[i*8+16],buffer[i*8+17],buffer[i*8+18],buffer[i*8+19]}) iftypeT==TYPET{ infoFound=true subOff=int64(f.unpack([]byte{buffer[i*8+20],buffer[i*8+21],buffer[i*8+22],buffer[i*8+23]})) break } } if!infoFound{ log.Fatalln("读取exe错误,找不到typeT==16.",f.FilePath) } subOff=subOff&0x7fffffff infoOff=f.unpack([]byte{buffer[subOff+20],buffer[subOff+21],buffer[subOff+22],buffer[subOff+23]})//offsetoffirstFILEINFO infoOff=infoOff&0x7fffffff infoOff=f.unpack([]byte{buffer[infoOff+20],buffer[infoOff+21],buffer[infoOff+22],buffer[infoOff+23]})//offsettodata dataOff:=f.unpack([]byte{buffer[infoOff],buffer[infoOff+1],buffer[infoOff+2],buffer[infoOff+3]}) dataOff=dataOff-infoVirt version1:=f.unpack([]byte{buffer[dataOff+48],buffer[dataOff+48+1]}) version2:=f.unpack([]byte{buffer[dataOff+48+2],buffer[dataOff+48+3]}) version3:=f.unpack([]byte{buffer[dataOff+48+4],buffer[dataOff+48+5]}) version4:=f.unpack([]byte{buffer[dataOff+48+6],buffer[dataOff+48+7]}) version:=fmt.Sprintf("%d.%d.%d.%d",version2,version1,version4,version3) f.Version=version returnnil } func(f*fileInfo)unpack(b[]byte)(numint64){ fori:=0;i<len(b);i++{ num=256*num+int64((b[len(b)-1-i]&0xff)) } return } //获取apk版本 func(f*fileInfo)GetApkVersion()(errerror){ listener:=new(axmlParser.AppNameListener) _,err=axmlParser.ParseApk(f.FilePath,listener) f.checkError(err) f.Version=listener.VersionName returnnil } funcinit(){ flag.StringVar(&file.FilePath,"path",DEFAULT,"Getexeordllorapkversioninformation.") flag.BoolVar(&file.Debug,"d",false,"iftrueprintexeordllfilename.") } funcmain(){ flag.Parse() suffix:=filepath.Ext(file.FilePath) switchsuffix{ case".exe",".dll": file.GetExeVersion() case".apk": file.GetApkVersion() default: log.Fatalln("仅能获取exe、dll、apk版本号,请重新输入程序路径.",file.FilePath) } switch{ casefile.Debug: fmt.Printf("%s的版本号为:",file.FilePath) casefile.FilePath==DEFAULT: flag.PrintDefaults() fmt.Printf("%s的版本号为:",file.FilePath) } fmt.Printf("%s",file.Version) }