HDCTF reverse部分复现 easy_re 首先查壳 是UPX壳,扔进虚拟机
直接脱壳
扔进ida 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int __cdecl main (int argc, const char **argv, const char **envp) { int i; _main(argc, argv, envp); func (a, encode_a); puts ("Please input your flag:" ); scanf ("%s" , s); for ( i = 1 ; i <= 32 ; ++i ) f3 (s); func (s, encode_s); if ( !strcmp (encode_s, a) ) puts ("Congratulations! You get the flag" ); else puts ("Sorry,try again" ); return 0 ; }
没什么好说的,逻辑很简单,s就是flag,s的加密就是a,而a是字符串“SERDVEZ7WTB1X2hAdjJfL1wvXEA1N2VyM2RfN2hlX3IzdjNyczN9”,跟进func加密函数,可以分析到这是一个base64加密,直接把a拿去base64解密就行。
HDCTF{Y0u_h@v2_//@57er3d_7he_r3v3rs3}
easy_arm 直接扔进ida 打开代码,分析代码,发现主要就做了两件事,输入字符串然后将字符串与0x10进行亦或操作,字符串也很好找,因为只有一串有效的字符串,那么就直接上脚本吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 val=[0x4E , 0x6F , 0x74 , 0x20 , 0x65 , 0x71 , 0x75 , 0x61 , 0x6C , 0x21 , 0x24 , 0x45 , 0x71 , 0x75 , 0x61 , 0x6C , 0x21 , 0x24 , 0x58 , 0x54 , 0x53 , 0x44 , 0x56 , 0x6B , 0x5A , 0x65 , 0x63 , 0x64 , 0x4F , 0x71 , 0x4F , 0x75 , 0x23 , 0x63 , 0x69 , 0x4F , 0x71 , 0x43 , 0x7D , 0x6D , 0x24 ] for i in val: print (chr (i),end='' ) realval='XTSDVkZecdOqOu#ciOqC}m' flag='' for i in realval: flag+=chr (ord (i)^0x10 ) print ()print (flag)
double_code shellcode类题目,也是第一次见,还是要先去了解一下什么是shellcode,实际上就是跑病毒的代码,这里也是先借鉴一下大佬的wp,补一补shellcode的姿势。
先进入函数sub_14001F000,这个函数就是加载shellcode的代码,这里提示了“WriteProcessMemory:%d\n”,说明是写入了病毒的,打开后这里就可以用opcode去做了。这里可以看出v7 v9 v11 v13是flag的四部分,其实v0或v1就是外部所给数据,那么就可以根据这段伪代码得到脚本,只需将数据根据每部分逻辑逆向即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 val=[0x48 ,0x67 ,0x45 ,0x51 ,0x42 ,0x7b ,0x70 ,0x6a ,0x30 ,0x68 ,0x6c ,0x60 ,0x32 ,0x61 ,0x61 ,0x5f ,0x42 ,0x70 ,0x61 ,0x5b ,0x30 ,0x53 ,0x65 ,0x6c ,0x60 ,0x65 ,0x7c ,0x63 ,0x69 ,0x2d ,0x5f ,0x46 ,0x35 ,0x70 ,0x75 ,0x7d ] flag="" for i in range (len (val)): key=i%5 if key==1 : flag+=chr (val[i]^0x23 ) elif key==2 : flag+=chr (val[i]-2 ) elif key==3 : flag+=chr (val[i]+3 ) elif key==4 : flag+=chr (val[i]+4 ) elif key==5 : flag+=chr (val[i]+25 ) else : flag+=chr (val[i]) print (flag)
fake_game 以前没做到过python打包的程序,所以看了一下做python打包程序的步骤,首先把程序用pyinstxtractor解包,具体步骤就是将要解包的程序放在pyinstxtractor文件根目录下,然后在根目录下打开终端,运行
1 python .\pyinstxtractor.py 文件名.类型
然后会在根目录下生成一个文件夹,在文件夹中我们可以找到解包好的文件名.pyc文件,然后将得到的pyc文件反编译
1 uncompyle6.exe ./文件名.pyc > 生成文件名.py
打开得到的py文件,找到了关键的flag字眼
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 def start_game (self ): global GAMEOVER xorr = [ 0 ] * 4 ans = [0 ] * 55 flag = [178868 , 188 , 56953 , 2413 , 178874 , 131 , 56957 , 2313 , 178867 , 156 , 56933 , 2377 , 178832 , 202 , 56899 , 2314 , 178830 , 167 , 56924 , 2313 , 178830 , 167 , 56938 , 2383 , 178822 , 217 , 56859 , 2372 ] self.init_window() self.init_plant_points() self.init_map() self.init_zombies() while not GAMEOVER: MainGame.window.fill((255 , 255 , 255 )) MainGame.window.blit(self.draw_text('当前钱数$: {}' .format (MainGame.money), 26 , (255 , 0 , 0 )), (500 , 40 )) MainGame.window.blit(self.draw_text('当前关数{},得分{},距离下关还差{}分' .format (MainGame.shaoguan, MainGame.score, MainGame.remnant_score), 26 , (255 , 0 , 0 )), (5 , 40 )) self.load_help_text() xorr[0 ] = MainGame.money xorr[1 ] = MainGame.shaoguan xorr[2 ] = MainGame.score xorr[3 ] = MainGame.remnant_score if xorr[0 ] * 256 - xorr[1 ] / 2 + xorr[2 ] * 23 + xorr[3 ] / 2 == 47118166 : if xorr[0 ] * 252 - xorr[1 ] * 366 + xorr[2 ] * 23 + xorr[3 ] / 2 - 1987 == 46309775 : if xorr[0 ] * 6 - xorr[1 ] * 88 + xorr[2 ] / 2 + xorr[3 ] / 2 - 11444 == 1069997 : if (xorr[0 ] - 652 ) * 2 - xorr[1 ] * 366 + xorr[2 ] * 233 + xorr[3 ] / 2 - 13333 == 13509025 : for i in range (len (flag)): ans[i] = flag[i] ^ xorr[i % 4 ] else : with open ('flag.txt' , 'w' ) as (f): f.write('' .join([chr (a) for a in ans]))
这里的逻辑也很简单,当游戏结束时,要满足if语句中的条件才能得到flag文件,这里直接用z3约束器求得xorr列表,再进行亦或即可,脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from z3 import *flag = [178868 , 188 , 56953 , 2413 , 178874 , 131 , 56957 , 2313 , 178867 , 156 , 56933 , 2377 , 178832 , 202 , 56899 , 2314 , 178830 , 167 , 56924 , 2313 , 178830 , 167 , 56938 , 2383 , 178822 , 217 , 56859 , 2372 ] flagg="" a,b,c,d=Ints('a b c d' ) s=Solver() s.add(a * 256 - b / 2 + c * 23 + d / 2 == 47118166 ) s.add(a * 252 - b * 366 + c * 23 + d / 2 - 1987 == 46309775 ) s.add(a * 6 - b * 88 + c / 2 + d / 2 - 11444 == 1069997 ) s.add((a - 652 ) * 2 - b * 366 + c * 233 + d / 2 - 13333 == 13509025 ) if s.check()==sat: print (s.model()) xorr=[178940 ,248 ,56890 ,2361 ] for i in range (len (flag)): flagg+=chr (flag[i]^xorr[i%4 ]) print (flagg)
但是这里出现了一个小问题,解出来的值最后一个数应该加上1才能得到完整的flag,可能是出题人弄错了,但是根据flag的格式也能得到。
买了些什么呢 直接拿出珍藏多年的01背包问题脚本
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 class good : def __init__ (self, num, eavy, value ): self.num = num self.value = value self.eavy = eavy self.avgvalue = value / eavy money = 0 weigt = 50 count = 40 goodlist = list () flag = list () for i in range (count): num, eavy, value = map (int , input ().split()) goodlist.append(good(num, eavy, value)) avglist = sorted (goodlist, key=lambda i: i.avgvalue, reverse=True ) for i in range (count): if weigt < 0 : break if avglist[i].eavy <= weigt: weigt -= avglist[i].eavy money += avglist[i].value flag.append(avglist[i].num) flag.sort() for i in range (len (flag)): flag[i] -= 1 print (money, weigt)for i in flag: print (i,end=" " )
输入回显的数据即可,注意修改weigt 和 count