Tags: golang cryptography math
Rating:
# The Most Worthy Distinction of Pain
```go
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
func readFlag() (string, error) {
flag_file, err := os.Open("flag.txt")
if err != nil {
return "", err
}
defer flag_file.Close()
scanner := bufio.NewScanner(flag_file)
scanner.Scan()
flag := scanner.Text()
return flag, nil
}
func combine(flag []uint8) []uint16 {
combined := []uint16{}
for i := 0; i < len(flag); i += 2 {
c := uint16(flag[i]) << 8
if i+1 < len(flag) {
c += uint16(flag[i+1])
}
combined = append(combined, c)
}
return combined
}
func encrypt(flag string) string {
codex_file, err := os.Open("CROSSWD.TXT")
if err != nil {
return "!"
}
defer codex_file.Close()
all_words := []string{}
combined := combine([]uint8(flag))
for _, c := range combined {
all_words = append(all_words, encode_one(c, codex_file))
}
return strings.Join(all_words, " ")
}
func encode_one(c uint16, codex_file *os.File) string {
codex_file.Seek(0, io.SeekStart)
scanner := bufio.NewScanner(codex_file)
for i := uint16(0); i < c; i++ {
scanner.Scan()
}
return scanner.Text()
}
func main() {
flag, err := readFlag()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(encrypt(flag))
}
```
it's all around the abyse of bit operations.
There, every second character was encrypted as follows:
ascii character code << 8 and add to it the ascii code of the next character (For example, 98 << 8 = 25088 + 121 = 25209), then, from the line number, which is equal to the received number, we take a word from the dictionary and substitute it into the ciphertext.
To decipher, it turns out we need to do the reverse operation: find a word in the dictionary, take its number, subtract the number X from it, and here stop, we don't know the number, that's where the abuz begins.
We can simply perform the reverse shift operation >>, without adding, and we will get the number to which we added (25088). For example, if we shift 25209 >> 8 = 98, and now if we shift 98 << 8, then we get 25088!!!! From here we get the following: 25209 - 25088 = 121, so we get all the numbers that are in even positions.
As part of the byuctf{testflag} test flag, it will be y c f t s f a }
And it's even easier to get odd ones, we just take the line numbers and move them (25209 >> 8 = 98)
```go
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
func readFlag() (string, error) {
flagFile, err := os.Open("encrypted.txt")
if err != nil {
return "", err
}
defer flagFile.Close()
scanner := bufio.NewScanner(flagFile)
scanner.Scan()
flag := scanner.Text()
return flag, nil
}
func combine(flag []uint8) []uint16 {
combined := []uint16{}
for i := 0; i < len(flag); i += 2 {
c := uint16(flag[i]) << 8
if i+1 < len(flag) {
c += uint16(flag[i+1])
}
combined = append(combined, c)
}
return combined
}
func revertCombine(flag []uint16) []uint16 {
combined := []uint16{}
for i := 0; i < len(flag); i += 1 {
c := flag[i] >> 8
combined = append(combined, c)
}
return combined
}
func encrypt(flag string) string {
codex_file, err := os.Open("CROSSWD.TXT")
if err != nil {
return "!"
}
defer codex_file.Close()
all_words := []string{}
combined := combine([]uint8(flag))
for _, c := range combined {
all_words = append(all_words, encodeOne(c, codex_file))
}
return strings.Join(all_words, " ")
}
func encodeOne(c uint16, codex_file *os.File) string {
codex_file.Seek(0, io.SeekStart)
scanner := bufio.NewScanner(codex_file)
for i := uint16(0); i < c; i++ {
scanner.Scan()
}
return scanner.Text()
}
func getLineNumber(myString string) (int, error) {
f, err := os.Open("CROSSWD.txt")
if err != nil {
return 0, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
line := 1
for scanner.Scan() {
if scanner.Text() == myString {
return line, nil
}
line++
}
if err := scanner.Err(); err != nil {
}
return 0, nil
}
func makeThatShit(flag_data []uint16) ([]uint16, []string) {
result_flag := revertCombine(flag_data)
second_flag_part := []string{}
for i, c := range result_flag {
c = c << 8
second_flag_part = append(second_flag_part, string(flag_data[i]-uint16(c)))
}
return result_flag, second_flag_part
}
func main() {
flag, err := readFlag()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(encrypt(flag))
words := strings.Fields(flag)
fmt.Println(words)
flag_data := []uint16{}
for _, c := range words {
lineNumber, _ := getLineNumber(c)
flag_data = append(flag_data, uint16(lineNumber))
}
fmt.Println(flag_data)
first, second := makeThatShit(flag_data)
for i := 0; i < len(first); i++ {
print(string(first[i]), second[i])
}
}
```