V0W's Blog

杭电Hgame2019-week1-WP

字数统计: 4,277阅读时长: 22 min
2019/02/01 Share

前言

说来也是有一点感慨的,去年我也是以萌新的身份参加的杭电hgame,我的第一篇博客好像也是那时候写的呢!算是有纪念意义呢,一年来学了一点知识,想再做一遍,看看菜鸡的水平有没有一星半点的成长。我主要做Web+Misc+Crypto,作为REbeginner,RE比较简单的,可以做一做,太菜了==、

Web

谁偷了我的flag

描述
呜呜呜,Mki一起床发现写好的题目变成这样了,是因为昨天没有好好关机吗T_T
URL http://118.25.111.31:10086/index.html

算是很清晰的了,vim非正常关机产生swp文件。本题为.index.html.swpvim -r index.html.swp还原。

1
hgame{3eek_diScl0Sure_fRom+wEbsit@}

换头大作战

描述
想要flag嘛
URL http://120.78.184.111:8080/week1/how/index.php

  1. POST
  2. X-Forwarded-For
  3. User-Agent
  4. Referer
  5. Cookie:admin=1

payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /week1/how/index.php HTTP/1.1
Host: 120.78.184.111:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Waterfox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
X-Forwarded-For: 127.0.0.1
Referer: www.bilibili.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 9
Cookie: admin=1
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

want=flag
1
hgame{hTTp_HeaDeR_iS_Ez}

very easy web

描述
代码审计初♂体验
URL http://120.78.184.111:8080/week1/very_ez/index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
error_reporting(0);
include("flag.php");

if(strpos("vidar",$_GET['id'])!==FALSE)
die("<p>干巴爹</p>");

$_GET['id'] = urldecode($_GET['id']);
if($_GET['id'] === "vidar")
{
echo $flag;
}
highlight_file(__FILE__);
?>

easy,发送数据会自动进行一次urldecode,故payload需要两次urlencode。

1
?id=%%37%36%69dar
1
hgame{urlDecode_Is_GoOd}

can u find me?

描述
为什么不问问神奇的十二姑娘和她的小伙伴呢
URL http://47.107.252.171:8080/

看源码,得<a href="f12.php"></a>跟进

1
2
but can you find the password?
please post password to me! I will open the gate for you!

发现要密码,在响应头中发现密码:password=woyaoflag

提交得到超链接,但是有302跳转,可以使用burp,得到flag。

1
hgame{f12_1s_aMazIng111}

Misc

Hidden Image in LSB

描述
Here are some magic codes which can hide information in an ordinary picture, can you extract the hidden image in the provided picture?
其实本来想让大家写写代码,后来干脆就送分了
有个神器叫 stegsolve,利用它可以直接提取本题 flag
URL http://plir4axuz.bkt.clouddn.com/hgame2019/lsb.zip

LSB

1
hgame{LSB_is_easy_for_u}

打字机

描述
Aris(划掉)牌打字机,时尚时尚最时尚~
hint:谷歌有个以图搜图功能很不错,百度识图好垃圾的。。。
URL http://plps4kyke.bkt.clouddn.com/打字机.zip

看着眼熟,google一下确实是京紫的打字机,找到对应的英文字母
https://www.bilibili.com/read/cv194341/
https://www.bilibili.com/read/cv154778/

1
hgame{My_vi0let_tyPewRiter}

中间的0有点坑,没啥意思。

Broken Chest

描述
这个箱子坏掉了!快用你无敌的[疯狂钻石]想想办法啊!
更新一波学习资料https://ctf-wiki.github.io/ctf-wiki/misc/archive/zip/
URL
http://plqfgjy5a.bkt.clouddn.com/Broken-Chest.zip

压缩包坏了,秉着应该不会难的想法,winhex打开,发现第一个字节有问题,修改完后打开,发现需要密码,看到注释,得到密码S0mETh1ng_U5efuL

1
hgame{Cra2y_D1aM0nd}

Try

描述
无字天书
URL http://plqfgjy5a.bkt.clouddn.com/try-it.pcapng

数据包分析,追踪一个有压缩包的流,得到压缩包的数据。

得到一个压缩包,发现里面有一个password.txt提示我们密码是hgame********说明有八位不确定==、爆破,先按照全数字爆破。

写了一个字典,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
import itertools as its
words = "0123456789"

r = its.product(words,repeat=8)
f = open("dic.txt","a")
for i in r:
f.write('hgame')
f.write("".join(i))
f.write("".join("\n"))
f.close()
print 'ok'

跑字典得到压缩密码

解压得到一个1.jpg

winhex发现有一个zip在文件末尾,提取出来,伪加密,解压得到一个1.doc。打开发现没东西,显示隐藏文字后出现flag。

1
hgame{59d28413e36019861498e823f3f41406}

Crypto

Mix

描述
–…/….-/….-/-…/–…/…–/…../..-./-…./-../-…./..-./–…/—-./….-/….-/–…/.—-/-…./-…/–…/-…/-…./..—/…../.—-/-…./-…./…–/….-/…–/—–/-…./…../–…/-.. So easy

莫斯+hex+凯撒+栅栏

1
hgame{E4sY_cRypt0}

perfect_secrecy!

描述
Mom told me OTP is perfect secrecy!(结果加上hgame{})
URL http://plqbnxx54.bkt.clouddn.com/easy_otp.py

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
import binascii
import string
import random

def strxor(a, b):
return "".join(hex(x ^ y)[2:].zfill(2) for (x, y) in zip(a, b))

def strunhex(s):
return "".join(binascii.a2b_hex(s))

fp = open('poem.txt', 'rb')
flag = "*********************************"
strings = fp.readlines()
strs = [strxor(i[:-3], binascii.unhexlify(key)) for i in strings]
result = strxor(flag.encode('utf-8'), binascii.unhexlify(key))
print(strs)
print(result)

'''
output:
['daaa4b4e8c996dc786889cd63bc4df4d1e7dc6f3f0b7a0b61ad48811f6f7c9bfabd7083c53ba54',
'c5a342468c8c7a88999a9dd623c0cc4b0f7c829acaf8f3ac13c78300b3b1c7a3ef8e193840bb',
'dda342458c897a8285df879e3285ce511e7c8d9afff9b7ff15de8a16b394c7bdab920e7946a05e9941d8308e',
'd9b05b4cd5ce7c8f938bd39e24d0df191d7694dfeaf8bfbb56e28900e1b8dff1bb985c2d5aa154',
'd9aa4b00c88b7fc79d99d38223c08d54146b88d3f0f0f38c03df8d52f0bfc1bda3d7133712a55e9948c32c8a',
'c4b60e46c9827cc79e9698936bd1c55c5b6e87c8f0febdb856fe8052e4bfc9a5efbe5c3f57ad4b9944de34',
'd9aa5700da817f94d29e81936bc4c1555b7b94d5f5f2bdff37df8252ffbecfb9bbd7152a12bc4fc00ad7229090',
'c4e24645cd9c28939a86d3982ac8c819086989d1fbf9f39e18d5c601fbb6dab4ef9e12795bbc549959d9229090',
'd9aa4b598c80698a97df879e2ec08d5b1e7f89c8fbb7beba56f0c619fdb2c4bdef8313795fa149dc0ad4228f',
'cce25d48d98a6c8280df909926c0de19143983c8befab6ff21d99f52e4b2daa5ef83143647e854d60ad5269c87',
'd9aa4b598c85668885df9d993f85e419107783cdbee3bbba1391b11afcf7c3bfaa805c2d5aad42995ede2cdd82977244',
'e1ad40478c82678995df809e2ac9c119323994cffbb7a7b713d4c626fcb888b5aa920c354be853d60ac5269199',
'c4ac0e53c98d7a8286df84936bc8c84d5b50889aedfebfba18d28352daf7cfa3a6920a3c',
'd9aa4f548c9a609ed297969739d18d5a146c8adebef1bcad11d49252c7bfd1f1bc87152b5bbc07dd4fd226948397',
'c4a40e698c9d6088879397d626c0c84d5b6d8edffbb792b902d49452ffbec6b6ef8e193840',
'c5ad5900df8667929e9bd3bf6bc2df5c1e6dc6cef6f2b6ff21d8921ab3a4c1bdaa991f3c12a949dd0ac5269c']
'c2967e7fc59d57899d8bac852ac3c866127fb9d7f1e5b68002d9871cccb8c6b2aa'
'''

题目意图很明显,一次安全的密钥,但是多次使用还安全吗

很显然,答案是否定的,多次使用一个密钥进行加密尤其是异或时,很容易出现安全问题。

参考这两篇文章小记一类ctf密码题解题思路http://dann.com.br/alexctf2k17-crypto100-many_time_secrets/

一般的解法有两种,一是通过字母出现的频率统计规律进行权重赋值。其实说白了就是字频攻击。

二是合理利用明文的空格

这种方法其实是利用了一个异或的规律和一个小技巧。空格和所有小写字母异或结果是相应的大写字母,空格和所有大写字母异或是相应的小写字母

我是用国外那位大佬的脚本跑的。

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/python
## OTP - Recovering the private key from a set of messages that were encrypted w/ the same private key (Many time pad attack) - crypto100-many_time_secret @ alexctf 2017
# @author intrd - http://dann.com.br/
# Original code by jwomers: https://github.com/Jwomers/many-time-pad-attack/blob/master/attack.py)

import string
import collections
import sets, sys

# 11 unknown ciphertexts (in hex format), all encrpyted with the same key
c1 = 'daaa4b4e8c996dc786889cd63bc4df4d1e7dc6f3f0b7a0b61ad48811f6f7c9bfabd7083c53ba54'
c2 = 'c5a342468c8c7a88999a9dd623c0cc4b0f7c829acaf8f3ac13c78300b3b1c7a3ef8e193840bb'
c3 = 'dda342458c897a8285df879e3285ce511e7c8d9afff9b7ff15de8a16b394c7bdab920e7946a05e9941d8308e'
c4 = 'd9b05b4cd5ce7c8f938bd39e24d0df191d7694dfeaf8bfbb56e28900e1b8dff1bb985c2d5aa154'
c5 = 'd9aa4b00c88b7fc79d99d38223c08d54146b88d3f0f0f38c03df8d52f0bfc1bda3d7133712a55e9948c32c8a'
c6 = 'c4b60e46c9827cc79e9698936bd1c55c5b6e87c8f0febdb856fe8052e4bfc9a5efbe5c3f57ad4b9944de34'
c7 = 'd9aa5700da817f94d29e81936bc4c1555b7b94d5f5f2bdff37df8252ffbecfb9bbd7152a12bc4fc00ad7229090'
c8 = 'c4e24645cd9c28939a86d3982ac8c819086989d1fbf9f39e18d5c601fbb6dab4ef9e12795bbc549959d9229090'
c9 = 'd9aa4b598c80698a97df879e2ec08d5b1e7f89c8fbb7beba56f0c619fdb2c4bdef8313795fa149dc0ad4228f'
c10 = 'cce25d48d98a6c8280df909926c0de19143983c8befab6ff21d99f52e4b2daa5ef83143647e854d60ad5269c87'
c11 = 'd9aa4b598c85668885df9d993f85e419107783cdbee3bbba1391b11afcf7c3bfaa805c2d5aad42995ede2cdd82977244'
c12 = 'e1ad40478c82678995df809e2ac9c119323994cffbb7a7b713d4c626fcb888b5aa920c354be853d60ac5269199'
c13 = 'c4ac0e53c98d7a8286df84936bc8c84d5b50889aedfebfba18d28352daf7cfa3a6920a3c'
c14 = 'd9aa4f548c9a609ed297969739d18d5a146c8adebef1bcad11d49252c7bfd1f1bc87152b5bbc07dd4fd226948397'
c15 = 'c4a40e698c9d6088879397d626c0c84d5b6d8edffbb792b902d49452ffbec6b6ef8e193840'
c16 = 'c5ad5900df8667929e9bd3bf6bc2df5c1e6dc6cef6f2b6ff21d8921ab3a4c1bdaa991f3c12a949dd0ac5269c'

ciphers = [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11,c12,c13,c14,c15,c16]
# The target ciphertext we want to crack
target_cipher = 'c2967e7fc59d57899d8bac852ac3c866127fb9d7f1e5b68002d9871cccb8c6b2aa'

# XORs two string
def strxor(a, b): # xor two strings (trims the longer input)
return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])

# To store the final key
final_key = [None]*150
# To store the positions we know are broken
known_key_positions = set()

# For each ciphertext
for current_index, ciphertext in enumerate(ciphers):
counter = collections.Counter()
# for each other ciphertext
for index, ciphertext2 in enumerate(ciphers):
if current_index != index: # don't xor a ciphertext with itself
for indexOfChar, char in enumerate(strxor(ciphertext.decode('hex'), ciphertext2.decode('hex'))): # Xor the two ciphertexts
# If a character in the xored result is a alphanumeric character, it means there was probably a space character in one of the plaintexts (we don't know which one)
if char in string.printable and char.isalpha(): counter[indexOfChar] += 1 # Increment the counter at this index
knownSpaceIndexes = []

# Loop through all positions where a space character was possible in the current_index cipher
for ind, val in counter.items():
# If a space was found at least 7 times at this index out of the 9 possible XORS, then the space character was likely from the current_index cipher!
if val >= 7: knownSpaceIndexes.append(ind)
#print knownSpaceIndexes # Shows all the positions where we now know the key!

# Now Xor the current_index with spaces, and at the knownSpaceIndexes positions we get the key back!
xor_with_spaces = strxor(ciphertext.decode('hex'),' '*150)
for index in knownSpaceIndexes:
# Store the key's value at the correct position
final_key[index] = xor_with_spaces[index].encode('hex')
# Record that we known the key at this position
known_key_positions.add(index)

# Construct a hex key from the currently known key, adding in '00' hex chars where we do not know (to make a complete hex string)
final_key_hex = ''.join([val if val is not None else '00' for val in final_key])
# Xor the currently known key with the target cipher
output = strxor(target_cipher.decode('hex'),final_key_hex.decode('hex'))

print "Fix this sentence:"
print ''.join([char if index in known_key_positions else '*' for index, char in enumerate(output)])+"\n"

# WAIT.. MANUAL STEP HERE
# This output are printing a * if that character is not known yet
# fix the missing characters like this: "Let*M**k*ow if *o{*a" = "cure, Let Me know if you a"
# if is too hard, change the target_cipher to another one and try again
# and we have our key to fix the entire text!

#sys.exit(0) #comment and continue if u got a good key

target_plaintext = "OTP_is_not_safe_if_more_than_once"
print "Fixed:"
print target_plaintext+"\n"

key = strxor(target_cipher.decode('hex'),target_plaintext)

print "Decrypted msg:"
for cipher in ciphers:
print strxor(cipher.decode('hex'),key)

print "\nPrivate key recovered: "+key+"\n"

通过修补很容易得到flag,再验证,基本上很快可以得到正确结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Fix this sentence:
*TP_:s_not_safe_if_more_tha&_once

Fixed:
OTP_is_not_safe_if_more_than_once

Decrypted msg:
When we two parted In silence and
Half broken hearted To sever for
Pale grew thy cheek and cold Cold
Truly that hour foretold Sorrow t
The dew of the morning Sunk chill
It felt like the warning Of what
Thy vows are all broken And light
I hear thy name spoken And share
They name thee before me A knell
A shudder comes o er me Why wert
They know not I knew thee Who kne
long long shall I rue thee Too de
In secret we met In silence I gri
That thy heart could forget Thy s
If I should meet thee After ling
How should I greet thee With sile

1
hgame{OTP_is_not_safe_if_more_than_once}

Base全家

描述
全家老小
URL http://plir4axuz.bkt.clouddn.com/hgame2019/enc.txt

多种base组合

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
#!/usr/bin/env python

import base64
import requests

def download(url):
return requests.get(url).text

steps = []
url = "http://plir4axuz.bkt.clouddn.com/hgame2019/enc.txt"

print "[+] Downloading encrypted file..."
p = download(url)
n = ""

while True:
# Base16
try:
print "[?] using base16 deocde"
n = base64.b16decode(p)
print "[+] %s" % (n)
steps.append(16)
p = n
continue
except:
pass
# Base32
try:
print "[?] using base32 deocde"
n = base64.b32decode(p)
print "[+] %s" % (n)
steps.append(32)
p = n
continue
except:
pass
# Base64
try:
print "[?] using base64 deocde"
n = base64.b64decode(p)
print "[+] %s" % (n)
steps.append(64)
p = n
continue
except:
pass
break

print "[+] flag found : %s" % (n)
print "[+] steps : %s" % (steps)

得到结果:

1
[+] base58 : 2BAja2VqXoHi9Lo5kfQZBPjq1EmZHGEudM5JyDPREPmS3CxrpB8BnC

http://lenschulwitz.com/base58 ,最后得到结果:

1
hgame{40ca78cde14458da697066eb4cc7daf6}

RE

Pro的Python教室(一)

描述
Easiest Python Challenge!
URL http://plqbnxx54.bkt.clouddn.com/first.py

不知道该怎怎么说,因为直接给出源码,太简单了==

1
hgame{Here_1s_3asy_Pyth0n}

HelloRe

描述
Welcoooooome!
URL http://plps4kyke.bkt.clouddn.com/HelloRe

IDA打开,Shift+F12得到结果:

回头看一眼代码,逻辑很简单:

1
hgame{Welc0m3_t0_R3_World!}

brainfxxker

描述
Ouch! What is this? I don’t think that I am pretty good at C++, what a brain fxxker it is!
学习资料:
https://zh.wikipedia.org/wiki/Brainfuck
https://zh.wikipedia.org/zh/ASCII
读懂我的代码逻辑答案就出来了
补充说明:
判定答案是否正确的是 Notice 2,即“不执行 [+.] 这个部分”,不要单纯看有没有输出 orz
URL http://plir4axuz.bkt.clouddn.com/hgame2019/brainfucker.cpp

解这个题,需要对brainfuck的逻辑有一定的理解才行。参考https://zh.wikipedia.org/wiki/Brainfuck

BF语言有两个字节流

一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流

字符 含义
> 指针加一
< 指针减一
+ 指针指向的字节的值加一
- 指针指向的字节的值减一
. 输出指针指向的单元内容(ASCII码
, 输入内容到指针指向的单元(ASCII码)
[ 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处
] 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处

于是这段C++代码实际上就是BF的C++实现,而本题的关键是这段BF代码(以[+.]分割开):

1
2
3
4
5
6
7
8
9
,>++++++++++[<---------->-]<++[+.]   
,>+++++++++[<--------->-]<-[+.]
,>+++++++[<------->-]<---[+.]
,>++++++[<------>-]<+++[+.]
,>++++++++[<---------->-]<++[+.]
,>++++++++++[<---------->-]<--[+.]
,>++++++++++[<-------->-]<-----[+.]
,>++++++++++[<---------->-]<+[+.]
,>+++++++++[<-------->-]<---[+.]

首先,为什么[+.]会报错?

因为

[ :如果指针指向单元值不为0,loop开始

+.:字节指针+1输出,但是该指针并没有指向任何数据,故报错

] :循环结束

那么若想[+.]不报错,则需要[之前的指针单元为0

以第一段为例(之后同理不做赘述):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
,	输入
> 指针右移
++++++++++ 循环变量设置为10
[ loop
< 指针左移,指向输入的值
---------- 输入变量减10
> 指针右移,指向循环变量
- 循环变量减1
(总共减了10次)
] 判断循环是否结束

< 指针左移,指向输入变量
++ 输入变量加2
[+.] = 0
----------------------华丽的分割线-------------------
x - 100 + 2 = 0
x = 98 chr(98)= b
1
hgame{bR4!NfUcK}

わかります

描述
POSITION ZERO!
URL http://plps4kyke.bkt.clouddn.com/wakarimasu

main函数逻辑简单:

输入一个值,然后通过一个函数判定是否符合要求。

但是这个函数稍稍复杂一点

将输入字符串简单处理以后得到v7ptr,然后与一个预定义的数组OrginalArr通过两个函数得到v8,v9

最后判断v8必须与数组arr1,v9必须与数组arr2相等。

func1是两个三维矩阵的乘,func2是两个二维矩阵的加法,z3约束

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from z3 import *

target1 = [122, 207, 140, 149, 142, 168,

95, 201, 122, 145, 136, 167,

112, 192, 127, 137, 134, 147,

95, 207, 110, 134, 133, 173,

136, 212, 160, 162, 152, 179,

121, 193, 126, 126, 119, 147]



token = [8, 1, 7, 1, 1, 0,

4, 8, 1, 2, 3, 9,

3, 8, 6, 6, 4, 8,

3, 5, 7, 8, 8, 7,

0, 9, 0, 2, 3, 4,

2, 3, 2, 5, 4, 0]



target2 = [16, 8, 8, 14, 6, 11,

5, 23, 5, 10, 12, 23,

14, 23, 19, 7, 8, 10,

4, 13, 22, 17, 11, 22,

6, 14, 2, 11, 18, 9,

5, 8, 8, 10, 16, 13]



chunk2 = [8, 7, 1, 13, 5, 11, 1, 15, 4, 8, 9, 14, 11, 15, 13, 1, 4, 2, 1, 8, 15, 9, 3, 15, 6, 5, 2, 9, 15, 5, 3, 5, 6, 5, 12, 13]



a = BitVec('a', 8)

b = BitVec('b', 8)

c = BitVec('c', 8)

d = BitVec('d', 8)

e = BitVec('e', 8)

f = BitVec('f', 8)

j = 0

k = 0

p = 0

for q in range(6):

solve((a >> 4) * token[k] + (b >> 4) * token[k + 6] + (c >> 4) * token[k + 12] + (d >> 4) * token[k + 18] + (e >> 4) * token[k + 24] + (f >> 4) * token[k + 30] == target1[j],

(a >> 4) * token[k + 1] + (b >> 4) * token[k + 6 + 1] + (c >> 4) * token[k + 12 + 1] + (d >> 4) * token[k + 18 + 1] + (e >> 4) * token[k + 24 + 1] + (f >> 4) * token[k + 30 + 1] == target1[j + 1],

(a >> 4) * token[k + 2] + (b >> 4) * token[k + 6 + 2] + (c >> 4) * token[k + 12 + 2] + (d >> 4) * token[k + 18 + 2] + (e >> 4) * token[k + 24 + 2] + (f >> 4) * token[k + 30 + 2] == target1[j + 2],

(a >> 4) * token[k + 3] + (b >> 4) * token[k + 6 + 3] + (c >> 4) * token[k + 12 + 3] + (d >> 4) * token[k + 18 + 3] + (e >> 4) * token[k + 24 + 3] + (f >> 4) * token[k + 30 + 3] == target1[j + 3],

(a >> 4) * token[k + 4] + (b >> 4) * token[k + 6 + 4] + (c >> 4) * token[k + 12 + 4] + (d >> 4) * token[k + 18 + 4] + (e >> 4) * token[k + 24 + 4] + (f >> 4) * token[k + 30 + 4] == target1[j + 4],

(a >> 4) * token[k + 5] + (b >> 4) * token[k + 6 + 5] + (c >> 4) * token[k + 12 + 5] + (d >> 4) * token[k + 18 + 5] + (e >> 4) * token[k + 24 + 5] + (f >> 4) * token[k + 30 + 5] == target1[j + 5],

a & 0xf == chunk2[p], b & 0xf == chunk2[p + 1], c & 0xf == chunk2[p + 2], d & 0xf == chunk2[p + 3], e & 0xf == chunk2[p + 4], f & 0xf == chunk2[p + 5])

j += 6

p += 6

#[f = 123, b = 103, a = 104, c = 97, d = 109, e = 101]

#[f = 110, b = 95, a = 49, c = 116, d = 104, e = 105]

#[f = 114, b = 95, a = 107, c = 77, d = 97, e = 116]

#[f = 95, b = 120, a = 49, c = 95, d = 105, e = 115]

#[f = 117, b = 101, a = 118, c = 114, d = 121, e = 95]

#[f = 125, b = 101, a = 115, c = 102, d = 53, e = 108]

flag = [104,103,97,109,101,123,49,95,116,104,105,110,107,95,77,97,116,114,49,120,95,105,115,95,118,101,114,121,95,117,115,101,102,53,108,125]

qwer = ""

for q in flag:

qwer += chr(q)

print(qwer)
#hgame{1_think_Matr1x_is_very_usef5l}

这题对我们这种REbeginner来说很不友好==、

r & xor

描述
论r 与 xor 的重要性 ida里奇怪的大数字?不如按r试一试
URL http://plir4axuz.bkt.clouddn.com/hgame2019/xor

IDA打开,选中长数字按r可以将其转成字符

从有往左读,可以发现这个是一个flag,但是不可能这么简单,没错,这是fake_flag,==、

memset(void *s, int ch,size_t n)需要注意,这个是初始化函数,将s后面n个字节都初始化成ch。

于是得到0x90/4=144/4=36。即将v6开始后面36个int都初始化为0。作为REbeginner我以为这里除了问题,因为给出的变量不足36个,但是后来经大佬提醒发现,这个要看定义的变量所占的内存,

一个int是4位,但是v7(bp-118h)v8(bp-110h)差了8位,就是说,v7和v8之间有两个int,一个是v7,一个是之前初始化的0,之后同理,可以推测出所有的36位数组序列。

1
2
[0,0,0,0,0,0,1,0,7,0,92,18,38,11,93,43,11,23,0,23,43,69,6,86,44,54,67,
0,66,85,126,72,85,30,0]

之后的就简单了,看一下代码逻辑,很简单的异或,再异或一下就可以得到真正的flag

脚本如下:

1
2
3
4
5
6
7
8
s = 'hgame{Y0u_mayb3_need_th1s_0ne!!!!!}'
v = [0,0,0,0,0,0,1,0,7,0,92,18,38,11,93,43,11,23,0,23,43,69,6,86,44,54,67,0,66,85,126,72,85,30,0]
flag = ''
for i in range(0,35):
flag += chr(ord(s[i])^v[i])
print flag

## hgame{X0r_1s_interest1ng_isn't_it?}
CATALOG
  1. 1. 前言
  2. 2. Web
    1. 2.1. 谁偷了我的flag
    2. 2.2. 换头大作战
    3. 2.3. very easy web
    4. 2.4. can u find me?
  3. 3. Misc
    1. 3.1. Hidden Image in LSB
    2. 3.2. 打字机
    3. 3.3. Broken Chest
    4. 3.4. Try
  4. 4. Crypto
    1. 4.1. Mix
    2. 4.2. perfect_secrecy!
    3. 4.3. Base全家
  5. 5. RE
    1. 5.1. Pro的Python教室(一)
    2. 5.2. HelloRe
    3. 5.3. brainfxxker
    4. 5.4. わかります
    5. 5.5. r & xor