興味本位でGo言語に触れてみようと思う。WSLで32bit Windows実行ファイルを生成して32bit DLLを呼び出すってしてみる。<--もうまじで需要なさそう;
まず32bit DLLを生成せんと動作確認できないので、32bit DLLつくる。Windows 32bitターゲットでビルドできる環境を用意せんといかんのだが、ここからはWSL Ubuntuでやることにして、WSLにMingwを入れておけばよいわけだ。ところで、DLLはVisual StudioとBuild toolsで作るのが正攻法だと思うが、(以前も書いたけど、)Visual Studio Community EditionのLicense Termsが気に入らないのでVisual Studioは使わない。で、実は以前記事にしていた( WSLでWindows実行ファイルを作るまでの地味な道のり(1)、 WSLでWindows実行ファイルを作るまでの地味な道のり(2) )ので環境整備に関しては省略(<--手抜きではない)。Go開発環境はUbuntuなら、「Go言語入門(1)」に書いた通りそのまんまでいい。<--注 : WSLのUbuntuはUbuntu-24.04にしないといけない。さもないと古いバージョンのgolangがインストールされる。
プロジェクトは~/work/go/calldll32に作っていくことにする。
まぁこんな感じ
- calldll32
- |-- calldll32.go
- `-- keeloq
- |-- Makefile
- |-- keeloq.c
- |-- keeloq.def
- `-- keeloq_call.c
keeloq/keeloq.c
- #include <stdio.h>
- #include <stdint.h>
-
- uint32_t __stdcall keeloq_enc(uint32_t pr,uint64_t kr){
- uint32_t nlf_table=0x3a5c742e;
- uint32_t nlf_arg;
- uint32_t nlf;
- uint32_t newz;
- uint32_t i;
- for(i=0;i<528;i++){
- nlf_arg=((pr&0x80000000)>>(31-4))
- |((pr&0x04000000)>>(26-3))
- |((pr&0x00100000)>>(20-2))
- |((pr&0x00000200)>>(9-1))
- |((pr&0x00000002)>>(1-0));
- nlf=((nlf_table>>nlf_arg)&0x00000001);
- newz=nlf^((pr&0x00010000)>>16)^(pr&0x00000001)^(uint32_t)(kr&0x0000000000000001);
- pr=(newz<<31)|(pr>>1);
- kr=((kr&0x0000000000000001)<<63)|(kr>>1);
- }
- return pr;
- }
- uint32_t __stdcall keeloq_dec(uint32_t cr,uint64_t kr){
- uint32_t nlf_table=0x3a5c742e;
- uint32_t nlf_arg;
- uint32_t nlf;
- uint32_t newz;
- uint32_t i;
- for(i=0;i<528;i++){
- nlf_arg=((cr&0x40000000)>>(30-4))
- |((cr&0x02000000)>>(25-3))
- |((cr&0x00080000)>>(19-2))
- |((cr&0x00000100)>>(8-1))
- |((cr&0x00000001)>>(0-0));
- nlf=((nlf_table>>nlf_arg)&0x00000001);
- newz=nlf^((cr&0x00008000)>>15)^((cr&0x80000000)>>31)^(uint32_t)((kr&0x0000000000008000)>>15);
- cr=(cr<<1)|(newz);
- kr=((kr&0x8000000000000000)>>63)|(kr<<1);
- }
- return cr;
- }
- #if 0
- int main(int argc,char** argv){
- uint32_t pr=0xf741e2db;
- uint64_t kr=0x5cec6701b79fd949;
- uint32_t cr;
- cr=keeloq_enc(pr,kr);
- printf("%08X\n",cr);
- pr=keeloq_dec(cr,kr);
- printf("%08X\n",pr);
- return 0;
- }
- #endif
keeloq/keeloq.def
- LIBRARY keeloq
- EXPORTS
- keeloq_enc
- keeloq_dec
keeloq/Makefile
- CC=/usr/bin/i686-w64-mingw32-gcc
- CXX=/usr/bin/i686-w64-mingw32-g++
- LINK=/usr/bin/i686-w64-mingw32-gcc
- CFLAGS= -Wall -c
- LFLAGS= -shared -static-libgcc -static-libstdc++
-
- keeloq.dll: keeloq.o
- $(LINK) $(LFLAGS) -o keeloq.dll keeloq.o keeloq.def
-
- keeloq.o: keeloq.c
- $(CC) $(CFLAGS) keeloq.c -c -o keeloq.o
-
- clean:
- rm keeloq.o keeloq.dll
keeloq/keeloq_call.c
- #include <stdio.h>
- #include <stdint.h>
- #include <windows.h>
- typedef uint32_t (__stdcall *keeloq_enc_type)(uint32_t pr,uint64_t kr);
- typedef uint32_t (__stdcall *keeloq_dec_type)(uint32_t cr,uint64_t kr);
- HMODULE dll;
- keeloq_enc_type keeloq_enc;
- keeloq_dec_type keeloq_dec;
-
- int main(int argc,char** argv){
- uint32_t pr=0xf741e2db;
- uint64_t kr=0x5cec6701b79fd949;
- uint32_t cr;
- dll=LoadLibrary("keeloq.dll");
- keeloq_enc=(keeloq_enc_type)GetProcAddress(dll,"keeloq_enc");
- keeloq_dec=(keeloq_dec_type)GetProcAddress(dll,"keeloq_dec");
-
- cr=keeloq_enc(pr,kr);
- printf("%08X\n",cr);
- pr=keeloq_dec(cr,kr);
- printf("%08X\n",pr);
- return 0;
- }
で、DLLを作って動作確認してみる。
cd keeloq
make
/usr/bin/i686-w64-mingw32-gcc keeloq_call.c
./a.exe
まぁ、こんなもんよ。
cd ..
で、goのコードを書いていく。DLLをcallするにはUbuntu Linuxでやった時と同じようにcgoを使う方法があるけど、今回は別の方法にしてみる。参考サイトはこちら(https://go.dev/wiki/WindowsDLLs)。で、こんなコードにする。
calldll32.go
- package main
-
- import (
- "fmt"
- "syscall"
- )
-
- var (
- hdll,_=syscall.LoadLibrary("keeloq\\keeloq.dll")
- keeloq_enc,_=syscall.GetProcAddress(hdll,"keeloq_enc")
- keeloq_dec,_=syscall.GetProcAddress(hdll,"keeloq_dec")
- )
-
- func Keeloq_enc(pr uint32,kr uint64)(cr uint32){
- var nargs uintptr=3
- ret,_,_:=syscall.Syscall9(uintptr(keeloq_enc),
- nargs,
- uintptr(pr),uintptr(kr),uintptr(kr>>32),0,0,0,0,0,0)
- cr=uint32(ret)
- return
- }
- func Keeloq_dec(cr uint32,kr uint64)(pr uint32){
- var nargs uintptr=3
- ret,_,_:=syscall.Syscall9(uintptr(keeloq_dec),
- nargs,
- uintptr(cr),uintptr(kr),uintptr(kr>>32),0,0,0,0,0,0)
- pr=uint32(ret)
- return
- }
-
- func main() {
- var pr uint32
- var cr uint32
- var kr uint64
- defer syscall.FreeLibrary(hdll)
- pr = 0xf741e2db
- kr = 0x5cec6701b79fd949
- cr = Keeloq_enc(pr, kr)
- fmt.Printf("%08X\n", cr)
- pr = Keeloq_dec(cr, kr)
- fmt.Printf("%08X\n", pr)
- }
で、
GOOS=windows GOARCH=386 go run calldll32.go
で、ビルドもしてみる。
GOOS=windows GOARCH=386 go build calldll32.go
ls -la
./calldll32.exe
うまくいった。
いちおう32bit windows実行ファイルであることを確認してみた。
はい。それらしくできています。
WSLでmingw使って実行ファイル作るとWSLの中で実行できる(Linuxなはずなのに.exeを実行できる)ってのが確かに便利だよね。
今日から2月。もう1年の12分の1(=8.33%)が過ぎ去ったと思うとなんか焦るね。人生はそんなに長くない。若い頃気付くべきだった。「やらなかった後悔より、やった後悔」(ニッコロ・マキャベリ)。やっちまった~ってのはすぐ忘れるか割り切れる。やっとけばよかった~ってのは忘れられないし傷が深い。
0 件のコメント:
コメントを投稿