-
-
[原创]kctf2021 第六题 寻回宝剑
-
2021-5-27 10:18 8406
-
flag: 02152S3X4Z5Q6C7T819/ADB%C*DLEIFUG3HRIHJ6K7L0MBNKOJPPQ=RNS+TEUOVWWGXYYMZ9+4-8*F/-%V=A
搜索程序字符串,并下断
在程序等待输入时暂停程序,输入完之后返回程序领空,找到程序输入函数的位置
打开x64dbg的追踪功能,追踪记录选择1字节,跟踪步进
程序停在输出失败的字符串上,查看跟踪记录,找cmp和跳转相关语句
(跟踪记录输出到文件出bug了,地址输出少了一个数)
根据语句猜测输入长度为0x54,在这里下断,下次跟踪从这里开始
尝试输入
QWERTYUIOPASDFGHJKLZXCVBNM123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()-=_+/*-+\][';
继续追踪程序,根据cmp及cmp后的跳转指令,发现输入的字符范围[0-9][A-Z]
尝试输入
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ233333333333
在1400906db下断,断下后观察内存
发现内存中的值正好是输入字符串每两个一组,42进制下的数值,且数值必须比上一组大
尝试输入
000102030405060708090A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z0+0-0*0/0%0=
在1400906db断下,开始跟踪,取消断点
发现这次je跳转由test引起
构造不同的输入并观察内存,发现是每一组的两个字符分成前后,前字符均不重复,后字符均不重复
由于必须大小有序,前字符固定了顺序
尝试输入
00112233445566778899AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ++--**//%%==
在140015f89断下,开始跟踪,取消断点
发现test指令均在一个地方
随机构造输入
ch='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%=' import random def change(n): return ch[n//42]+ch[n%42] b=[i for i in range(42)] s='' random.shuffle(b) for i in range(42): print("%.2x"%b[i],end=',') print() num=[i*42+b[i] for i in range(42)] for i in range(42): s+=change(num[i]) print(s)
结合内存内容,发现RAX是两个数据差值,RCX是与两个数据位置差与差值正负相关,且对应位置不能>=2
观察到字符串 02152S3X4Z5Q6C7T819/ADB%C*DL 符合这个形式,猜测是输入开头
将这个开头转换
ch='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%=' flag='02152S3X4Z5Q6C7T819/ADB%C*DL' b=[i for i in range(42)] fb=[] cid=0 for c in flag: cid+=1 if(cid %2 ==0): fb.append(b.pop(b.index(ch.find(c)))) print(fb)
得到
2, 5, 28, 33, 35, 26, 12, 29, 1, 39, 13, 40, 38, 21
基于此进行爆破
#include<stdio.h> int fixed[]={2, 5, 28, 33, 35, 26, 12, 29, 1, 39, 13, 40, 38, 21}; int ran[]={0, 3, 4, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 27, 30, 31, 32, 34, 36, 37, 41}; int ans[50]={0}; int calc(int ans_len){ int hi[42][42]={0}; int lo[42][42]={0}; for(int i=0;i<ans_len-1;i++){ int numa=ans[i]; for(int j=1;j<ans_len-i;j++){ int numb=ans[i+j]; int diff=numb-numa; if(diff>0){ hi[j][diff]+=1; } if(diff<0){ lo[j][-diff]+=1; } } } for(int i=0;i<ans_len;i++){ for(int j=0;j < ans_len;j++){ if(hi[i][j]>=2){ return 0; } if(lo[i][j]>=2){ return 0; } } } if(ans_len==42){ for(int i=0;i<ans_len;i++){ printf("%d,",ans[i]); } printf("\n"); } return 1; } void dfs(int ans_len){ for(int i=0;i<28;i++){ int curnumber=ran[i]; int canfill=1; for(int j=14;j<ans_len;j++){ if(ans[j]==curnumber){ canfill=0; break; } } if(canfill){ ans[ans_len]=curnumber; if(calc(ans_len+1)){ dfs(ans_len+1); } ans[ans_len]=0; } } return; } int main(){ for(int i=0;i<14;i++){ ans[i]=fixed[i]; } dfs(14); }
得到结果
2,5,28,33,35,26,12,29,1,39,13,40,38,21,18,30,3,27,17,6,7,0,11,20,19,25,41,23,36,14,24,32,16,34,22,9,4,8,15,37,31,10
转换输入
s='' ch='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%=' def change(n): return ch[n//42]+ch[n%42] snum=[2,5,28,33,35,26,12,29,1,39,13,40,38,21,18,30,3,27,17,6,7,0,11,20,19,25,41,23,36,14,24,32,16,34,22,9,4,8,15,37,31,10] num=[i*42+snum[i] for i in range(42)] for i in range(42): s+=change(num[i]) print(s)
得到正确输入
02152S3X4Z5Q6C7T819/ADB%C*DLEIFUG3HRIHJ6K7L0MBNKOJPPQ=RNS+TEUOVWWGXYYMZ9+4-8*F/-%V=A
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课