Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to encrypt sha1 binary file #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions cmd_encrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"os"

"github.com/freemyipod/wInd3x/pkg/app"
"github.com/freemyipod/wInd3x/pkg/exploit/encryptsha1"
"github.com/golang/glog"
"github.com/spf13/cobra"
)

var encryptSHA1Cmd = &cobra.Command{
Use: "encrypt [input] [output]",
Short: "Encrypt truncated binary sha1 hash file",
Long: "Uses a connected device to encrypt a sha1 hash in order to allow for creating valid IMG1 headers (v1/3/4) or IMG1 (v2) files.\nThis is used to manually assemble valid IMG1 headers (for easy exploitation of pwnage 2.0 or to create valid IMG1 v2 files for the iPod Nano 3g. Simply generate a binary sha1 file of the header (0x40 bytes) using a command like (openssl dgst -binary -sha1 header_file_0x40_bytes) then use a hex editor or a command like head to delete the last four bytes of the sha1 hash and produce a 0x10 byte long file that will be encrypted with the AES engine.\nThis encrypted hash can then used to assemble a valid IMG1 header or should be able to produce a full IMG1 on devices that support IMG1v2(iPod Nano 3g), assuming you encrypt the body sha1 in the appropriate place as well.",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
f, err := os.ReadFile(args[0])
if err != nil {
return fmt.Errorf("Failed to read sha1 file: %w", err)
}

app, err := app.New()
if err != nil {
return err
}
defer app.Close()

res, err := encryptsha1.Encryptsha1(app, f)
if err != nil {
return err
}

// Write sha1file.
if err := os.WriteFile(args[1], res, 0600); err != nil {
return fmt.Errorf("could not write image: %w", err)
}

glog.Infof("Done!")

return nil
},
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func main() {
rootCmd.AddCommand(makeDFUCmd)
rootCmd.AddCommand(dumpCmd)
rootCmd.AddCommand(decryptCmd)
rootCmd.AddCommand(encryptSHA1Cmd)
nandCmd.AddCommand(nandReadCmd)
rootCmd.AddCommand(nandCmd)
norCmd.AddCommand(norReadCmd)
Expand Down
86 changes: 86 additions & 0 deletions pkg/exploit/encryptsha1/encryptsha1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package encryptsha1

import (
"bytes"
"fmt"
"time"

"github.com/golang/glog"
"github.com/google/gousb"

"github.com/freemyipod/wInd3x/pkg/app"
"github.com/freemyipod/wInd3x/pkg/dfu"
"github.com/freemyipod/wInd3x/pkg/exploit"
"github.com/freemyipod/wInd3x/pkg/uasm"
)

// Payload creates a payload which encrypts 0x10 bytes from the DFU
// buffer into the DFU buffer using a zero IV and the Global key.
// This is useful for creating custom IMG1s
func Payload(ep exploit.Parameters) ([]byte, error) {
insns := ep.DisableICache()
insns = append(insns, ep.AESEncryptSha1()...)
insns = append(insns, ep.HandlerFooter(ep.DFUBufAddr())...)
payload := uasm.Program{
Address: ep.ExecAddr(),
Listing: insns,
}

return payload.Assemble(), nil
}

func Trigger(usb *gousb.Device, ep exploit.Parameters, data []byte) ([]byte, error) {
if err := dfu.Clean(usb); err != nil {
return nil, fmt.Errorf("clean failed: %w", err)
}
payload, err := Payload(ep)
if err != nil {
return nil, fmt.Errorf("failed to generate payload: %w", err)
}

dataCopy := make([]byte, 0x10)
copy(dataCopy, data)
res, err := exploit.RCE(usb, ep, payload, dataCopy)
if err != nil {
return nil, fmt.Errorf("failed to execute encrypt sha1: %w", err)
}

return res, nil
}

func Encryptsha1(app *app.App, in []byte) ([]byte, error) {
if len(in) != 0x10{
glog.Infof("Found input sha1 hash as 0x%x bytes. This has should be exactly 0x10 bytes long", len(in))
return nil, fmt.Errorf("Input sha1 hash is wrong size.")
}
glog.Infof("Encrypting sha1 hash 0x%x bytes...", len(in))
w := bytes.NewBuffer(nil)


tries := 10
var res []byte
for {
data := make([]byte, 0x10)
copy(data[:0x10], in[:0x10])

var err error
res, err = Trigger(app.Usb, app.Ep, data)
if err == nil {
break
}
if tries < 1 {
return nil, fmt.Errorf("Encryption failed, and out of retries: %w", err)
} else {
glog.Infof("Encryption failed (%v), retrying...", err)
time.Sleep(100 * time.Millisecond)
tries -= 1
}
}

sha1aes := res[:0x10]
if _, err := w.Write(sha1aes); err != nil {
return nil, fmt.Errorf("write failed: %w", err)
}

return w.Bytes(), nil
}
1 change: 1 addition & 0 deletions pkg/exploit/exploit.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Parameters interface {

HandlerFooter(addr uint32) []uasm.Statement
AESCall() []uasm.Statement
AESEncryptSha1() []uasm.Statement
HaxedDFUPayload() []uasm.Statement
DisableICache() []uasm.Statement

Expand Down
4 changes: 4 additions & 0 deletions pkg/exploit/exploit_n3g.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func (_ *epNano3G) AESCall() []uasm.Statement {
return makeCall(0x20001f04, 0x22028220, 0x40, 1, 0, 0)
}

func (_ *epNano3G) AESEncryptSha1() []uasm.Statement {
return makeCall(0x20001f64, 0x22028220, 0x10, 1, 0, 0)
}

func (_ *epNano3G) HaxedDFUPayload() []uasm.Statement {
return []uasm.Statement{
// Copy descriptor to g_State->deviceDescriptor.
Expand Down
8 changes: 8 additions & 0 deletions pkg/exploit/exploit_n45g.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ func (_ *epNano4G) AESCall() []uasm.Statement {
return makeCall(0x200020d4, 0x2202db00, 0x2202db00, 0x40, 1, 0, 0)
}

func (_ *epNano4G) AESEncryptSha1() []uasm.Statement {
return makeCall(0x200021b8, 0x2202db00, 0x2202db00, 0x10, 1, 0, 0)
}

func (_ *epNano4G) DisableICache() []uasm.Statement {
return makeCall(0x200003f4)
}
Expand Down Expand Up @@ -168,6 +172,10 @@ func (_ *epNano5G) AESCall() []uasm.Statement {
return makeCall(0x200020ec, 0x2202db00, 0x2202db00, 0x40, 1, 0, 0)
}

func (_ *epNano5G) AESEncryptSha1() []uasm.Statement {
return makeCall(0x200021d0, 0x2202db00, 0x2202db00, 0x10, 1, 0, 0)
}

func (_ *epNano5G) DisableICache() []uasm.Statement {
return makeCall(0x200003c0)
}
Expand Down