题目描述
我们得到了一串神秘字符串:TASC?O3RJMV?WDJKX?ZM,问号部分是未知大写字母,为了确定这个神秘字符串,我们通过了其他途径获得了这个字串的32位MD5码。但是我们获得它的32位MD5码也是残缺不全,E903???4DAB????08?????51?80??8A?,请猜出神秘字符串的原本模样,并且提交这个字串的32位MD5码作为答案。 注意:得到的 flag 请包上 flag{} 提交
WriteUp
先穷举,共有26^3^种可能的字符串,然后进行MD5编码,将得到的MD5码和已知的残缺码比对,匹配成功就输出当前字符串及其MD5码。
具体步骤:
- 将模板字符串
TASC?O3RJMV?WDJKX?ZM
中的 ?
记录下来(共 3 个)。
- 枚举这 3 个位置的所有大写字母组合(263=17576263=17576 种)。
- 对每个候选字符串计算 MD5(128 bit → 32 位十六进制)。
- 用正则把已知的 MD5 片段
E903???4DAB????08?????51?80??8A?
匹配进去。
匹配成功即得到答案。
使用GO编写穷举比对代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| package main
import ( "crypto/md5" "encoding/hex" "fmt" "regexp" )
func main() {
str := []byte("TASC?O3RJMV?WDJKX?ZM") var qIdx []int for i, letter := range str { if letter == '?' { qIdx = append(qIdx, i) } }
if len(qIdx) != 3 { panic("?不是3个") }
md5Pattern := `(?i)^E903[0-9a-f]{3}4DAB[0-9a-f]{4}08[0-9a-f]{5}51[0-9a-f]{1}80[0-9a-f]{2}8A[0-9a-f]{1}$` re := regexp.MustCompile(md5Pattern)
allLetter := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ") for _, letter1 := range allLetter { str[qIdx[0]] = letter1 for _, letter2 := range allLetter { str[qIdx[1]] = letter2 for _, letter3 := range allLetter { str[qIdx[2]] = letter3
cand := string(str) sum := md5.Sum([]byte(cand)) hash := hex.EncodeToString(sum[:])
md5Upper := fmt.Sprintf("%X\n", sum)
if re.MatchString(hash) { fmt.Println("MD5:", hash) fmt.Println("大写:", md5Upper) fmt.Println("原字符串:", cand) return } } } } fmt.Println("未匹配到符合条件的字符串") }
|
得到flag{E9032994DABAC08080091151380478A2}