move again

This commit is contained in:
olebeck 2022-09-04 16:53:21 +02:00
parent 4892b1f5e2
commit 6a4d4bdf4a
26 changed files with 301 additions and 14 deletions

View File

@ -10,7 +10,11 @@ import (
"regexp"
"syscall"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
_ "github.com/bedrock-tool/bedrocktool/subcommands"
_ "github.com/bedrock-tool/bedrocktool/subcommands/skins"
_ "github.com/bedrock-tool/bedrocktool/subcommands/world"
"github.com/google/subcommands"
"github.com/sirupsen/logrus"

8
go.mod
View File

@ -1,4 +1,4 @@
module bedrocktool
module github.com/bedrock-tool/bedrocktool
go 1.19
@ -34,9 +34,9 @@ require (
github.com/jinzhu/copier v0.3.5
github.com/klauspost/compress v1.15.9 // indirect
github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect
github.com/sandertv/go-raknet v1.11.1
github.com/sirupsen/logrus v1.9.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
github.com/sandertv/go-raknet v1.11.1 // indirect
github.com/sirupsen/logrus v1.9.0
go.uber.org/atomic v1.10.0
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect

2
go.sum
View File

@ -55,6 +55,8 @@ github.com/olebeck/gophertunnel v1.24.8-2 h1:T7WY2M/GrKTOgcH1RcDiB8LNlhK+PEzGdHS
github.com/olebeck/gophertunnel v1.24.8-2/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
github.com/olebeck/gophertunnel v1.24.8-3 h1:qR5PCFWUAcUureCt36tLqaXWOjHVsFx66PiKm1obtkY=
github.com/olebeck/gophertunnel v1.24.8-3/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
github.com/olebeck/gophertunnel v1.24.8-4 h1:V0Giy93JYDzR6NhtXOw/UcWpY85Jt/czp7xcAfJz22Y=
github.com/olebeck/gophertunnel v1.24.8-4/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
github.com/olebeck/gophertunnel v1.24.8 h1:jdqBOABDAE1yISqzm9IxIrI+/lJApLBjTieynXUSalw=
github.com/olebeck/gophertunnel v1.24.8/go.mod h1:dMOw79FHxr2azEqiGH20AwdljisAN1kqwu5SjPBnZ5k=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

View File

@ -1,4 +1,4 @@
package main
package subcommands
import (
"bytes"
@ -10,7 +10,7 @@ import (
"os"
"time"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"

View File

@ -1,4 +1,4 @@
package main
package subcommands
import (
"context"
@ -8,7 +8,7 @@ import (
"os"
"time"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/df-mc/dragonfly/server/world/mcdb"
"github.com/df-mc/goleveldb/leveldb/opt"

View File

@ -6,7 +6,7 @@ import (
"fmt"
"os"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/google/subcommands"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"

View File

@ -13,7 +13,7 @@ import (
"path"
"strings"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/flytam/filenamify"
"github.com/google/subcommands"

View File

@ -4,7 +4,7 @@ import (
"image"
"image/color"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/df-mc/dragonfly/server/block"
"github.com/df-mc/dragonfly/server/block/cube"

View File

@ -9,7 +9,7 @@ import (
"sync"
"time"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/sandertv/gophertunnel/minecraft/protocol"

View File

@ -15,7 +15,7 @@ import (
"strings"
"time"
"bedrocktool/cmd/bedrocktool/utils"
"github.com/bedrock-tool/bedrocktool/utils"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/world"

View File

@ -0,0 +1,281 @@
package utils
import (
"archive/zip"
"bytes"
"context"
"crypto/aes"
"encoding/json"
"flag"
"fmt"
"io"
"os"
"path"
"strings"
"github.com/flytam/filenamify"
"github.com/google/subcommands"
"github.com/sandertv/gophertunnel/minecraft"
"github.com/sandertv/gophertunnel/minecraft/resource"
"github.com/sirupsen/logrus"
)
const KEYS_FILE = "keys.db"
// decrypt using cfb with segmentsize = 1
func cfb_decrypt(data []byte, key []byte) ([]byte, error) {
cipher, err := aes.NewCipher([]byte(key))
if err != nil {
return nil, err
}
shift_register := append(key[:16], data...)
iv := make([]byte, 16)
off := 0
for ; off < len(data); off += 1 {
cipher.Encrypt(iv, shift_register)
data[off] ^= iv[0]
shift_register = shift_register[1:]
}
return data, nil
}
type content_item struct {
Path string `json:"path"`
Key string `json:"key"`
}
type Content struct {
Content []content_item `json:"content"`
}
type Pack struct {
resource.Pack
}
func (p *Pack) ReadAll() ([]byte, error) {
buf := make([]byte, p.Len())
off := 0
for {
n, err := p.ReadAt(buf[off:], int64(off))
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
off += n
}
return buf, nil
}
func (p *Pack) Decrypt() ([]byte, error) {
data, err := p.ReadAll()
if err != nil {
return nil, err
}
z, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
return nil, err
}
zip_out_buf := bytes.NewBuffer(nil)
zw := zip.NewWriter(zip_out_buf)
written := make(map[string]interface{})
// read key contents file
var content Content = Content{}
{
ff, err := z.Open("contents.json")
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}
} else {
fw, _ := zw.Create("contents.json")
buf, _ := io.ReadAll(ff)
if err := json.Unmarshal(buf, &content); err != nil {
dec, _ := cfb_decrypt(buf[0x100:], []byte(p.ContentKey()))
dec = bytes.Split(dec, []byte("\x00"))[0]
fw.Write(dec)
if err := json.Unmarshal(dec, &content); err != nil {
return nil, err
}
} else {
fw.Write(buf)
}
written["contents.json"] = true
}
}
// decrypt each file in the contents file
for _, entry := range content.Content {
ff, _ := z.Open(entry.Path)
stat, _ := ff.Stat()
if ff == nil || stat.IsDir() {
continue
}
buf, _ := io.ReadAll(ff)
if entry.Key != "" {
buf, _ = cfb_decrypt(buf, []byte(entry.Key))
}
fw, _ := zw.Create(entry.Path)
fw.Write(buf)
written[entry.Path] = true
}
// copy files not in the contents file
for _, src_file := range z.File {
if written[src_file.Name] == nil {
zw.Copy(src_file)
}
}
zw.Close()
return zip_out_buf.Bytes(), nil
}
func dump_keys(keys map[string]string) {
f, err := os.OpenFile(KEYS_FILE, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0o775)
if err != nil {
panic(err)
}
defer f.Close()
data, err := io.ReadAll(f)
if err != nil {
panic(err)
}
lines := strings.Split(strings.ReplaceAll(string(data), "\r\n", "\n"), "\n")
existing_keys := map[string]string{}
for _, v := range lines {
if len(v) == 0 {
continue
}
item := strings.Split(v, "=")
existing_keys[item[0]] = item[1]
}
for uuid, key := range keys {
if key == "" {
continue
}
existing := existing_keys[uuid]
if existing != "" {
logrus.Warnf("key %s exists already\n", uuid)
if existing != key {
logrus.Warnf("uuid:%s, key in db: %s != new key %s\n", uuid, existing, key)
}
continue
}
f.WriteString(uuid + "=" + key + "\n")
}
}
type ResourcePackCMD struct {
server_address string
save_encrypted bool
}
func (*ResourcePackCMD) Name() string { return "packs" }
func (*ResourcePackCMD) Synopsis() string { return "download resource packs from a server" }
func (c *ResourcePackCMD) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.server_address, "address", "", "remote server address")
f.BoolVar(&c.save_encrypted, "save-encrypted", false, "save encrypted resourcepacks")
}
func (c *ResourcePackCMD) Usage() string {
return c.Name() + ": " + c.Synopsis() + "\n" + SERVER_ADDRESS_HELP
}
func (c *ResourcePackCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
address, hostname, err := ServerInput(c.server_address)
if err != nil {
fmt.Fprint(os.Stderr, err)
return 1
}
serverConn, err := ConnectServer(ctx, address, nil, true, nil)
if err != nil {
fmt.Fprint(os.Stderr, err)
return 1
}
serverConn.Close()
logrus.Info("Received")
if len(serverConn.ResourcePacks()) > 0 {
logrus.Info("Decrypting Resource Packs")
dir := "packs/" + hostname
os.MkdirAll(dir, 0o777)
pack_names := make(map[string]int)
for _, pack := range serverConn.ResourcePacks() {
pack_names[pack.Name()] += 1
}
// dump keys, download and decrypt the packs
keys := make(map[string]string)
for _, pack := range serverConn.ResourcePacks() {
pack := &Pack{*pack}
keys[pack.UUID()] = pack.ContentKey()
pack_name := pack.Name()
if pack_names[pack_name] >= 2 {
pack_name += "_" + pack.UUID()
}
pack_name, _ = filenamify.FilenamifyV2(pack_name)
logrus.Infof("ResourcePack(Id: %s Key: %s | Name: %s %s)\n", pack.UUID(), keys[pack.UUID()], pack_name, pack.Version())
if c.save_encrypted {
data, err := pack.ReadAll()
if err != nil {
fmt.Fprint(os.Stderr, err)
return 1
}
os.WriteFile(path.Join(dir, pack_name+".zip"), data, 0o644)
}
logrus.Infof("Decrypting...")
data, err := pack.Decrypt()
if err != nil {
fmt.Fprint(os.Stderr, err)
return 1
}
os.WriteFile(path.Join(dir, pack_name+".mcpack"), data, 0o644)
}
logrus.Infof("Writing keys to %s", KEYS_FILE)
dump_keys(keys)
} else {
logrus.Warn("No Resourcepack sent")
}
fmt.Printf("Done!\n")
return 0
}
func init() {
RegisterCommand(&ResourcePackCMD{})
}
func GetPacks(server *minecraft.Conn) (packs map[string]*resource.Pack, err error) {
packs = make(map[string]*resource.Pack)
for _, pack := range server.ResourcePacks() {
_pack := &Pack{*pack}
if _pack.Encrypted() {
data, err := _pack.Decrypt()
if err != nil {
return nil, err
}
pack2, err := resource.FromBytes(data)
if err != nil {
return nil, err
}
packs[pack.Name()] = pack2
} else {
packs[pack.Name()] = pack
}
}
return
}