move again
This commit is contained in:
parent
4892b1f5e2
commit
6a4d4bdf4a
|
@ -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"
|
||||
|
|
Binary file not shown.
8
go.mod
8
go.mod
|
@ -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
2
go.sum
|
@ -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=
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue