108 lines
22 KiB
Go
108 lines
22 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"os/exec"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func checkUtility(utility string) {
|
|
if _, err := exec.LookPath(utility); err != nil {
|
|
fmt.Printf("%s is not installed. Please install it and try again.\n", utility)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
requiredUtils := []string{"argon2", "xxd", "bc"}
|
|
|
|
for _, utils := range requiredUtils {
|
|
checkUtility(utils)
|
|
}
|
|
|
|
var challenge string
|
|
if len(os.Args) < 2 {
|
|
reader := bufio.NewReader(os.Stdin)
|
|
fmt.Print("Enter Challenge Code: ")
|
|
challenge, _ = reader.ReadString('\n')
|
|
challenge = strings.TrimSpace(challenge)
|
|
} else {
|
|
challenge = strings.TrimSpace(os.Args[1])
|
|
}
|
|
|
|
// Validate the challenge format
|
|
matched, _ := regexp.MatchString(`^([0-9]+):([0-9]+):([A-Za-z0-9]+):([0-9]+)$`, challenge)
|
|
if !matched {
|
|
fmt.Println("Invalid challenge format. Expected format: memory_cost:time_cost:salt:difficulty")
|
|
os.Exit(2)
|
|
}
|
|
|
|
// Parse challenge code
|
|
parts := strings.Split(challenge, ":")
|
|
memoryCost := parts[0]
|
|
timeCost := parts[1]
|
|
salt := parts[2]
|
|
difficulty := parts[3]
|
|
|
|
// Debugging output
|
|
fmt.Printf("Memory Cost: %s\n", memoryCost)
|
|
fmt.Printf("Time Cost: %s\n", timeCost)
|
|
fmt.Printf("Salt: %s\n", salt)
|
|
fmt.Printf("Difficulty: %s\n", difficulty)
|
|
|
|
// Generate prefix for the password
|
|
pwPrefix := fmt.Sprintf("UNBLOCK-%s-", randomString(8))
|
|
difficultyRaw := int(math.Exp(math.Log(256) * (4 - math.Log(float64(parseInt(difficulty))) / math.Log(256))))
|
|
|
|
fmt.Printf("Estimated iterations: %s\n", difficulty)
|
|
fmt.Printf("Time Cost: %s\n\n", timeCost)
|
|
|
|
n := 1
|
|
startTime := time.Now()
|
|
|
|
// Main loop to find the solution
|
|
for {
|
|
pw := fmt.Sprintf("%s%d", pwPrefix, n)
|
|
cmd := exec.Command("bash", "-c", fmt.Sprintf("echo -n '%s' | argon2 %s -t %s -k %s -p 1 -id -v 13 -r", pw, salt, timeCost, memoryCost))
|
|
hashResult, err := cmd.Output()
|
|
if err != nil {
|
|
fmt.Println("Error executing argon2:", err)
|
|
return
|
|
}
|
|
|
|
hashBytes := string(hashResult)
|
|
hashSlice := strings.Split(hashBytes, "$")
|
|
hashHex := hashSlice[3][:8]
|
|
|
|
if parseInt(hashHex) < difficultyRaw {
|
|
fmt.Printf("\nSOLUTION FOUND\n")
|
|
fmt.Printf("Your unblock code is: %s\n", pw)
|
|
fmt.Println("This is the code you enter into the site to pass the challenge.\n")
|
|
break
|
|
} else {
|
|
elapsedTime := time.Since(startTime).Seconds()
|
|
fmt.Printf("\rElapsed Time: %.0f seconds.", elapsedTime)
|
|
n++
|
|
}
|
|
}
|
|
}
|
|
|
|
func randomString(length int) string {
|
|
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
b := make([]byte, length)
|
|
for i := range b {
|
|
b[i] = charset[rand.Intn(len(charset))]
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
func parseInt(s string) int {
|
|
i, _ := strconv.ParseInt(s, 16, 0)
|
|
return int(i)
|
|
} |