singnine
签到题,拖入IDA可以直接看到flag
seed
拖入IDA反编译,
发现flag与密匙进行异或操作得到密文,但是密匙来自随机数rand(),不过幸好前面有一个随机数种子seed。追踪进去发现seed没有值,所以此处应该是默认值0。但是由于rand()是c中<cstdlib>库的函数,python中没有,又懒得用c,索性一波动调直接获取随机数的值。
断点下在第33行,点击F9(Debugger => start process)开始调试。
进入之后flag随便输,随后F5反编译,找到断点处,追踪上面的v5获取其值
拿到密匙之后就很好操作了。直接与密文异或就行
exp
flag = ""
s = [0x26,0x45,0x49,0x8e,0x0b9,0x43,0x0cd,0x9b,0x0fa,0xc] # 密匙
ss = "40h, 29h, 28h, 0E9h, 0C2h, 4h, 0A4h, 0EDh, 9Fh, 53h, 5Fh, 75h, 3Ch, 0D1h, 0CDh, 2Bh, 0A8h, 0C4h, 89h, 69h, 15h, 21h, 16h, 0EFh, 0D7h, 27h, 92h, 0DFh, 0CAh, 53h, 5Fh, 2Ah, 3Ch, 0D1h, 0CEh, 3h, 0A3h, 0EFh, 0A5h, 78h, 16h, 1Ah, 2Dh, 0E1h, 0C4h, 3" # 密文
ss_list = ss.split("h, ")
for i in range(len(ss_list)):
print(ss_list[i])
flag += chr(int(ss_list[i],16) ^ s[i%10])
print(flag)
Run_润?
{
int v3; // [rsp+30h] [rbp+10h]
switch ( a2 )
{
case 'a':
v3 = a1 - 1;
goto LABEL_12;
case 'd':
v3 = a1 + 1;
goto LABEL_12;
case 'q':
v3 = a1 - 64;
if ( --dword_408040 < 0 )
{
puts("You crossed the line!Get out of here!");
exit(0);
}
goto LABEL_11;
case 's':
v3 = a1 + 8;
goto LABEL_12;
case 'u':
v3 = a1 + 64;
if ( ++dword_408040 > 7 )
{
puts("You crossed the line!Get out of here!");
exit(0);
}
LABEL_11:
sub_401A26();
goto LABEL_12;
case 'w':
v3 = a1 - 8;
LABEL_12:
if ( v3 > 511 )
goto LABEL_16;
if ( dword_408060[v3] )
{
out_num = 1;
puts("You crossed the line!Get out of here!");
exit(0);
}
return v3;
default:
LABEL_16:
puts("You crossed the line!Get out of here!");
exit(0);
}
}
查看主要函数,可以将此题想象成一个迷宫,宽度是8,长是8,有8层,整体呈一个正方形。
出口在编号511的位置上。不能越界,不能踩雷LABEL_12标签用于判断是否“踩雷”,输入有61个,起点在左上角。
以起点又第一个为数原点创建坐标系,出口的坐标是编号为511的位置,也就是最后一个点。
现在动调依次获取迷宫的地图:
0 1 0 0 0 0 0 0
0 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
第一张地图 ↑ 路径ssdddssu
1 1 1 0 1 1 1 0
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
第二张地图 路径u
1 1 1 0 1 1 1 0
1 1 1 1 1 1 1 0
1 1 1 1 1 0 0 0
1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
第三张地图 路径u
1 1 1 0 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 0 1 0 1 1
1 1 1 0 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
第四张地图 路径wwww u(qqqdddduussaau)
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
第五张地图 路径u(此处可以很清晰地看出来上一张地图的走法是括号中的那个)
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1
0 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1
0 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1
第六张地图 路径aaaaassssqddddddduu
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 0 0 0
1 1 1 1 1 0 1 0
1 1 1 1 1 1 1 0
1 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1
第七张地图 路径wwwaasu
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 0 1 1
1 1 1 1 1 0 0 0
第八章地图 路径sssdd
所以这道题的路径就是__ssdddssuuuwwwwqqqdddduussaauuuaaaaassssqddddddduuwwwaasusssdd__
正常运行程序输入路径可以得到flag
ps:所以到底这个地图是咋来的,一点都不明白,还原算法失败了,算了就先这样吧。
ease_re
拿到题后丢入IDA反编译
可以看出,加密非常直观简介:
Str[i] = (Str[i] >> 4) | (16 * Str[i]);
从单个字符的角度来看,加密就是:先是 原字符位右移“>>”四位 然后或“|” 16(也就是2^4)*原字符,也就是每字节flag前后4bit内容交换一下!
那么解密也很简单了,只要让密文再跑一次这个算法就行。
脚本写的不好,没上面的思路清晰,还请师傅们不要嫌弃T_T)
exp
flag = ""
str1 ="66h, 0C6h, 16h, 76h, 0B7h, 45h, 27h, 97h, 0F5h, 47h, 3h, 0F5h, 37h, 3h, 0C6h, 67h, 33h, 0F5h, 47h, 86h, 56h, 0F5h, 26h, 96h, 0E6h, 16h, 27h, 97h, 0F5h, 7h, 27h, 3h, 26h, 0C6h, 33h, 0D6h, 0D7h, 1B"
str_ls = str1.split("h, ")
for i in range(len(str_ls)): # 获得的密文字符串的字节内存在形式(bit位上的二进制)
str_ls[i] = str(bin(int(str_ls[i],16)))[2:]
k = 8 - len(str_ls[i])
str_ls[i] = '0' * k + str_ls[i]
print(str_ls)
for i in str_ls:
flag += chr(int(i[4:9] + i[0:4],2))
print(flag)
pycode
打开文本文档,是一连串的汇编语言
读完之后发现将4替换为c,t替换为0,-替换为+之后倒过来再进行base64解码并与8异或即可得到flag。
exp:
import base64
s = ''
ss = "==AeAF3M-tzO-giQ-AUQosDQ9tGK7MDPuhC47tDNB5Tb8Yn4sdW4"
for i in range(len(ss)-1,-1,-1):
if ss[i]=='4':
s +='c'
elif ss[i]=='-':
s += '+'
elif ss[i]=='t':
s += '0'
else:
s += ss[i]
s = base64.b64decode(s)
ss = ""
for i in s.decode():
ss += chr((ord(i)-3)^8)
print(ss)
ex_asm
拿到题目之后发现是一个txt文档,里面是汇编代码(asm),最后一行是加密后的密文
.text:0000000000401550 var_4= dword ptr -4
.text:0000000000401550
.text:0000000000401550 55 push rbp
.text:0000000000401551 48 89 E5 mov rbp, rsp
.text:0000000000401554 48 83 EC 30 sub rsp, 30h
.text:0000000000401558 E8 33 01 00 00 call __main
.text:0000000000401558
.text:000000000040155D C7 45 FC 00 00 00 00 mov [rbp+var_4], 0
.text:0000000000401564 EB 4B jmp short loc_4015B1
.text:0000000000401564
.text:0000000000401566 ; ---------------------------------------------------------------------------
.text:0000000000401566
.text:0000000000401566 loc_401566: ; CODE XREF: main+65↓j
.text:0000000000401566 8B 45 FC mov eax, [rbp+var_4]
.text:0000000000401569 48 98 cdqe
.text:000000000040156B 48 8D 15 AE 1A 00 00 lea rdx, flag
.text:0000000000401572 0F B6 04 10 movzx eax, byte ptr [rax+rdx]
.text:0000000000401576 83 F0 1E xor eax, 1Eh
.text:0000000000401579 89 C1 mov ecx, eax
.text:000000000040157B 8B 45 FC mov eax, [rbp+var_4]
.text:000000000040157E 48 98 cdqe
.text:0000000000401580 48 8D 15 99 1A 00 00 lea rdx, flag
.text:0000000000401587 88 0C 10 mov [rax+rdx], cl
.text:000000000040158A 8B 45 FC mov eax, [rbp+var_4]
.text:000000000040158D 48 98 cdqe
.text:000000000040158F 48 8D 15 8A 1A 00 00 lea rdx, flag
.text:0000000000401596 0F B6 04 10 movzx eax, byte ptr [rax+rdx]
.text:000000000040159A 83 E8 0A sub eax, 0Ah
.text:000000000040159D 89 C1 mov ecx, eax
.text:000000000040159F 8B 45 FC mov eax, [rbp+var_4]
.text:00000000004015A2 48 98 cdqe
.text:00000000004015A4 48 8D 15 75 1A 00 00 lea rdx, flag
.text:00000000004015AB 88 0C 10 mov [rax+rdx], cl
.text:00000000004015AE FF 45 FC inc [rbp+var_4]
.text:00000000004015AE
.text:00000000004015B1
.text:00000000004015B1 loc_4015B1: ; CODE XREF: main+14↑j
.text:00000000004015B1 83 7D FC 27 cmp [rbp+var_4], 27h ; '''
.text:00000000004015B5 7E AF jle short loc_401566
.text:00000000004015B5
.text:00000000004015B7 48 8D 15 62 1A 00 00 lea rdx, flag
.text:00000000004015BE 48 8D 0D 3B 2A 00 00 lea rcx, Format ; "%s"
.text:00000000004015C5 E8 76 15 00 00 call printf
.text:00000000004015C5
.text:00000000004015CA B8 00 00 00 00 mov eax, 0
.text:00000000004015CF 48 83 C4 30 add rsp, 30h
.text:00000000004015D3 5D pop rbp
.text:00000000004015D4 C3 retn
.text:00000000004015D4
nhuo[M`7mc7uhc$7midgbTf`7`$7%#ubf7 ci5Y
最下面是密文,可以看到,在0x401566和0x4015B5处分别跳转了两次,分析得出flag加密应该是在loc_401566里。
扫视整段发现有xor(异或)、sub(减),推测应该是加密算法。逆向一下:先加0x0a再异或0x1e。
exp:
str = "nhuo[M`7mc7uhc$7midgbTf`7`$7%#ubf7 ci5Y"
for i in str:
print(chr((ord(i)+0x0a)^0x1e),end='')
ease_math
这道题倒是不难,只是函数很大,乍一看很难解而已
拿到程序,发现是py源代码:
rint("Please input flag:")
flag = input()
if len(flag)!=42:
print("Check your length!")
exit()
l=[]
for i in range(6):
s=""
for j in flag[i*7:i*7+7]:
s+=hex(ord(j))[2:]
l.append(int(s,16))
if (
(593*l[0] + 997*l[1] + 811*l[2] + 258*l[3] + 829*l[4] + 532*l[5])== 0x5b8e0aef71d34ff43 and \
(605*l[0] + 686*l[1] + 328*l[2] + 602*l[3] + 695*l[4] + 576*l[5])== 0x551a262360964ef7f and \
(373*l[0] + 512*l[1] + 449*l[2] + 756*l[3] + 448*l[4] + 580*l[5])== 0x49d158a5657d6931c and \
(560*l[0] + 635*l[1] + 422*l[2] + 971*l[3] + 855*l[4] + 597*l[5])== 0x625568d5abbabf4f3 and \
(717*l[0] + 507*l[1] + 388*l[2] + 925*l[3] + 324*l[4] + 524*l[5])== 0x50ee0c025e70e3c23 and \
(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x40e735f8aa2815f65):
print("Good job!")
else:
print("Wrong\nTry again!!!")
exit()
逻辑很简单啊,flag七字符一份,共分六份。每份转为十六进制字符串后将字符串放在列表里转成一个十六进制数然后放在一个一元六次函数组里!!!这万恶的解方程…
我们用库函数解
exp:
from sympy import *
# 定义未知数的列表
l = symbols('l[0], l[1], l[2], l[3], l[4], l[5]')
# 定义并初始化方程组
eq1 = Eq(593 * l[0] + 997 * l[1] + 811 * l[2] + 258 * l[3] + 829 * l[4] + 532 * l[5], 0x5b8e0aef71d34ff43)
eq2 = Eq(605 * l[0] + 686 * l[1] + 328 * l[2] + 602 * l[3] + 695 * l[4] + 576 * l[5], 0x551a262360964ef7f)
eq3 = Eq(373 * l[0] + 512 * l[1] + 449 * l[2] + 756 * l[3] + 448 * l[4] + 580 * l[5], 0x49d158a5657d6931c)
eq4 = Eq(560 * l[0] + 635 * l[1] + 422 * l[2] + 971 * l[3] + 855 * l[4] + 597 * l[5], 0x625568d5abbabf4f3)
eq5 = Eq(717 * l[0] + 507 * l[1] + 388 * l[2] + 925 * l[3] + 324 * l[4] + 524 * l[5], 0x50ee0c025e70e3c23)
eq6 = Eq(312 * l[0] + 368 * l[1] + 884 * l[2] + 518 * l[3] + 495 * l[4] + 414 * l[5], 0x40e735f8aa2815f65)
# 用 solve 函数求解
sol = solve((eq1, eq2, eq3, eq4, eq5, eq6), (l[0], l[1], l[2], l[3], l[4], l[5]), dict=True)
# 输出解
print(sol)
# 取出对应值分别转化为2位的16进制数再转成字符
ss = ''
s = ''
for kay in sol[0]:
ss += hex(sol[0][kay])[2:]
print(ss)
for i in range(0,len(ss),2):
s += chr(int(ss[i:i+2],16))
print(s)
Authur`s_box
下载附件拿到了一个奇怪的文件,首先查一下壳,无壳,是exe程序
更改后缀拖入IDA反编译
进去之后发现逻辑相当清晰,一个非常熟悉的 strcmp函数把密文送到手里,再往前看,一个byte_408AB0与flag的异或。不过追踪进去发现里面没有值,可能需要动调一下(如果这个值的产生过程和flag无关的话)。
向上看有个函数,还有一堆循环和判断。继续向上看就是正常的输入以及检验输入长度了。
那么这道题的唯一难点就只有20行的不知名函数了,追踪进去看看:
到这里突然发现,虽然str(也就是flag)被传入,但是这个函数却和它没有关系,仅仅只是把它当做参数罢了。所以这道题没有其他的加密,只有一个异或罢了。看到这里我已经开始狂喜了。之前说什么来着?
只要被异或的值产生过程与flag无关,我们就可以直接动调获取他的值!到这里我们就可以着手写脚本了
师傅们看脚本:
ls = [ 0x56, 0x2B, 0x2E, 0x30, 0xB1, 0x55, 0xBA, 0x12, 0x8E, 0x31,
0xE6, 0xEE, 0xE6, 0x71, 0xF4, 0xE8, 0x4C, 0xE4, 0xB8, 0x79,
0x32, 0xC8, 0x0F, 0x4F, 0xF4, 0xDD, 0x33, 0xC5, 0x5F, 0x1C,
0xDE, 0x5A, 0x58, 0xF1, 0x0B, 0xFB, 0x35, 0xD7, 0x9A, 0xA1,
0xB6, 0x13]
value = [0x30, 0x47, 0x4F, 0x57, 0xCA, 0x34, 0xDF, 0x77, 0xEF, 0x08,
0xDE, 0xDE, 0xD7, 0x5C, 0xC7, 0x8D, 0x75, 0xD2, 0x95, 0x4D,
0x04, 0xFC, 0x39, 0x62, 0xCD, 0xE4, 0x51, 0xFD, 0x72, 0x7E,
0xEA, 0x6F, 0x68, 0xC1, 0x6E, 0x98, 0x06, 0xE5, 0xAF, 0x96,
0x84, 0x6E]
for i in range(42):
print(chr(ls[i]^value[i]),end='')
签到题?
先说一句,这是一道很让人费解的题,好在最后写出来了,努力没有白费。
拿到题之后,拖入IDA查看,3~108行是一系列数据定义和赋值,此处略过。
简单分析后易得,第110行对应输入,134行及以下对应输出。但是中间一大堆加密算法,光是看看就很绝望。
- 好,这里先不分析算法,等解出来flag之后我们再回头详细说这个。
我们先尝试运行一下程序,熟悉熟悉流程:输入之后经过加密,输出密文.
这时候我们应该想到在这道题目中,没有要求输入flag,但是他却有flag转换成的密文,也就是说flag至少在程序运行的过程中出现过一次。再联想到之前那一大串的赋值,可以推测flag应该就藏在里面。
但是此处只是赋值,对应的值只有程序运行的时候才能保存到相应地址上,目前为空值,所以此处不妨动调一波。
先将断点下到109行(赋值刚结束的地方)。随后点F9动调,F5再次反编译,依次追踪进去查看变量的值,发现是一堆连续的地址。
随后将复制后的地址全部选中,SHIFT + E取出所有变量内的值(变量的地址是从0x4ffb08~0x4ffcb7)
将值提取出来之后写脚本获取flag,但是会发现,这个flag不对,有许多不可见字符和空格。
-
我们提取到的东西不是flag,反而更像密文,那么怎么解密呢?
-
这时候我们想到刚开始被我们忽略的中间那一段算法,现在想来那个应该就是解密函数了,也就是说真正的flag值应该藏在下面的解密函数之后。到这里我们既很容易明白这道题的思路了
-
这道题的出题思路就是:
首先给出一段密文。然后解密,随后根据用户的输入再加密。下面是帮助理解的模拟代码
-
所以我们需要做的仅仅只是把断点挪到解密函数之后,然后再取一次值就好了
不断点击F8(单步执行)或点击F9运行到下一个断点处,再次取追踪取出之前那一连串地址中的值。
然后编写脚本将值转换成字符,这次发现没有不可见字符了,但是还是不对劲,这个flag居然连下划线都没有!尝试提交也不对,难道这里不是flag?我的思路错了吗?不,不是这样的
这个思路不应该出问题的啊,又想到这个里面连下划线都没有,我突然产生了一种大胆的猜测:这会不会也是一个密文?假设这也是一个密文,可是它却没有不可见字符,密文内也没有其他提示,所以直接大胆推测一波这是base64加密。嘿,越想越有搞头索性尝试一下,这不试不打紧,一试就知道,稳了。