//聽golang聽实现读取exe聽dll聽apk聽版本号 package聽main import聽( 聽聽聽聽"flag" 聽聽聽聽"fmt" 聽聽聽聽"log" 聽聽聽聽"os" 聽聽聽聽"path/filepath" ) import聽( 聽聽聽聽"github.com/lunny/axmlParser" ) var聽( 聽聽聽聽file聽fileInfo ) const聽( 聽聽聽聽MZ聽聽聽聽聽聽聽=聽"MZ" 聽聽聽聽PE聽聽聽聽聽聽聽=聽"PE" 聽聽聽聽RSRC聽聽聽聽聽=聽".rsrc" 聽聽聽聽TYPET聽聽聽聽=聽16 聽聽聽聽PEOFFSET聽=聽64 聽聽聽聽MACHINE聽聽=聽332 聽聽聽聽DEFAULT聽聽=聽`C:\Windows\System32\cmd.exe` ) type聽fileInfo聽struct聽{ 聽聽聽聽FilePath聽string 聽聽聽聽Version聽聽string 聽聽聽聽Debug聽聽聽聽bool } func聽(f聽*fileInfo)聽checkError(err聽error)聽{ 聽聽聽聽if聽err聽!=聽nil聽{ 聽聽聽聽聽聽聽聽log.Fatalln(err) 聽聽聽聽} } //聽获取exe聽dll版本 func聽(f聽*fileInfo)聽GetExeVersion()聽(err聽error)聽{ 聽聽聽聽file,聽err聽:=聽os.Open(f.FilePath) 聽聽聽聽f.checkError(err) 聽聽聽聽//聽第一次读取64聽byte 聽聽聽聽buffer聽:=聽make([]byte,聽64) 聽聽聽聽_,聽err聽=聽file.Read(buffer) 聽聽聽聽f.checkError(err) 聽聽聽聽defer聽file.Close() 聽聽聽聽str聽:=聽string(buffer[0])聽+聽string(buffer[1]) 聽聽聽聽if聽str聽!=聽MZ聽{ 聽聽聽聽聽聽聽聽log.Fatalln("读取exe错误,找不到聽MZ.",聽f.FilePath) 聽聽聽聽} 聽聽聽聽peOffset聽:=聽f.unpack([]byte{buffer[60],聽buffer[61],聽buffer[62],聽buffer[63]}) 聽聽聽聽if聽peOffset聽<聽PEOFFSET聽{ 聽聽聽聽聽聽聽聽log.Fatalln("peOffset聽读取错误.",聽f.FilePath) 聽聽聽聽} 聽聽聽聽//聽读取从文件开头移位到聽peOffset,第二次读取聽24聽byte 聽聽聽聽_,聽err聽=聽file.Seek(int64(peOffset),聽0) 聽聽聽聽buffer聽=聽make([]byte,聽24) 聽聽聽聽_,聽err聽=聽file.Read(buffer) 聽聽聽聽f.checkError(err) 聽聽聽聽str聽=聽string(buffer[0])聽+聽string(buffer[1]) 聽聽聽聽if聽str聽!=聽PE聽{ 聽聽聽聽聽聽聽聽log.Fatalln("读取exe错误,找不到聽PE.",聽f.FilePath) 聽聽聽聽} 聽聽聽聽machine聽:=聽f.unpack([]byte{buffer[4],聽buffer[5]}) 聽聽聽聽if聽machine聽!=聽MACHINE聽{ 聽聽聽聽聽聽聽聽log.Fatalln("machine聽读取错误.",聽f.FilePath) 聽聽聽聽} 聽聽聽聽noSections聽:=聽f.unpack([]byte{buffer[6],聽buffer[7]}) 聽聽聽聽optHdrSize聽:=聽f.unpack([]byte{buffer[20],聽buffer[21]}) 聽聽聽聽//聽读取从当前位置移位到聽optHdrSize,第三次读取聽40聽byte 聽聽聽聽file.Seek(int64(optHdrSize),聽1) 聽聽聽聽resFound聽:=聽false 聽聽聽聽for聽i聽:=聽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]) 聽聽聽聽聽聽聽聽if聽str聽==聽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,第四次读取聽infoSize聽byte 聽聽聽聽file.Seek(int64(infoOff),聽0) 聽聽聽聽buffer聽=聽make([]byte,聽infoSize) 聽聽聽聽_,聽err聽=聽file.Read(buffer) 聽聽聽聽f.checkError(err) 聽聽聽聽nameEntries聽:=聽f.unpack([]byte{buffer[12],聽buffer[13]}) 聽聽聽聽idEntries聽:=聽f.unpack([]byte{buffer[14],聽buffer[15]}) 聽聽聽聽var聽infoFound聽bool 聽聽聽聽var聽subOff,聽i聽int64 聽聽聽聽for聽i聽=聽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]}) 聽聽聽聽聽聽聽聽if聽typeT聽==聽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]})聽//offset聽of聽first聽FILEINFO 聽聽聽聽infoOff聽=聽infoOff聽&聽0x7fffffff 聽聽聽聽infoOff聽=聽f.unpack([]byte{buffer[infoOff+20],聽buffer[infoOff+21],聽buffer[infoOff+22],聽buffer[infoOff+23]})聽//offset聽to聽data 聽聽聽聽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 聽聽聽聽return聽nil } func聽(f聽*fileInfo)聽unpack(b聽[]byte)聽(num聽int64)聽{ 聽聽聽聽for聽i聽:=聽0;聽i聽<聽len(b);聽i++聽{ 聽聽聽聽聽聽聽聽num聽=聽256*num聽+聽int64((b[len(b)-1-i]聽&聽0xff)) 聽聽聽聽} 聽聽聽聽return } //聽获取聽apk聽版本 func聽(f聽*fileInfo)聽GetApkVersion()聽(err聽error)聽{ 聽聽聽聽listener聽:=聽new(axmlParser.AppNameListener) 聽聽聽聽_,聽err聽=聽axmlParser.ParseApk(f.FilePath,聽listener) 聽聽聽聽f.checkError(err) 聽聽聽聽f.Version聽=聽listener.VersionName 聽聽聽聽return聽nil } func聽init()聽{ 聽聽聽聽flag.StringVar(&file.FilePath,聽"path",聽DEFAULT,聽"Get聽exe聽or聽dll聽or聽apk聽version聽information.") 聽聽聽聽flag.BoolVar(&file.Debug,聽"d",聽false,聽"if聽true聽print聽exe聽or聽dll聽file聽name.") } func聽main()聽{ 聽聽聽聽flag.Parse() 聽聽聽聽suffix聽:=聽filepath.Ext(file.FilePath) 聽聽聽聽switch聽suffix聽{ 聽聽聽聽case聽".exe",聽".dll": 聽聽聽聽聽聽聽聽file.GetExeVersion() 聽聽聽聽case聽".apk": 聽聽聽聽聽聽聽聽file.GetApkVersion() 聽聽聽聽default: 聽聽聽聽聽聽聽聽log.Fatalln("仅能获取exe、dll、apk版本号,请重新输入程序路径.",聽file.FilePath) 聽聽聽聽} 聽聽聽聽switch聽{ 聽聽聽聽case聽file.Debug: 聽聽聽聽聽聽聽聽fmt.Printf("%s聽的版本号为:聽",聽file.FilePath) 聽聽聽聽case聽file.FilePath聽==聽DEFAULT: 聽聽聽聽聽聽聽聽flag.PrintDefaults() 聽聽聽聽聽聽聽聽fmt.Printf("%s聽的版本号为:聽",聽file.FilePath) 聽聽聽聽} 聽聽聽聽fmt.Printf("%s",聽file.Version) }
本文出自 “CodyGuo” 博客,请务必保留此出处http://codyguo.blog.51cto.com/10440635/1700347
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)