這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
//聽golang聽實現讀取exe聽dll聽apk聽版本號碼package聽mainimport聽(聽聽聽聽"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