BUUCTF Reverse WriteUp 2 简单注册器 是个APK,使用dex2jar
反编译之后用jd(java decompiler)
查看内容
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 package com.example.flag;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v7.app.ActionBarActivity;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class MainActivity extends ActionBarActivity { protected void onCreate (Bundle paramBundle) { super .onCreate(paramBundle); setContentView(2130903063 ); if (paramBundle == null ) getSupportFragmentManager().beginTransaction().add(2131034172 , new PlaceholderFragment()).commit(); Button button = (Button)findViewById(2131034175 ); final TextView textview = (TextView)findViewById(2131034174 ); button.setOnClickListener(new View.OnClickListener() { public void onClick (View param1View) { int i = 1 ; String str = editview.getText().toString(); if (str.length() != 32 || str.charAt(31 ) != 'a' || str.charAt(1 ) != 'b' || str.charAt(0 ) + str.charAt(2 ) - 48 != 56 ) i = 0 ; if (i == 1 ) { char [] arrayOfChar = "dd2940c04462b4dd7c450528835cca15" .toCharArray(); arrayOfChar[2 ] = (char )(arrayOfChar[2 ] + arrayOfChar[3 ] - 50 ); arrayOfChar[4 ] = (char )(arrayOfChar[2 ] + arrayOfChar[5 ] - 48 ); arrayOfChar[30 ] = (char )(arrayOfChar[31 ] + arrayOfChar[9 ] - 48 ); arrayOfChar[14 ] = (char )(arrayOfChar[27 ] + arrayOfChar[28 ] - 97 ); for (i = 0 ;; i++) { String str1; if (i >= 16 ) { str1 = String.valueOf(arrayOfChar); textview.setText("flag{" + str1 + "}" ); return ; } String str2 = str1[31 - i]; str1[31 - i] = str1[i]; str1[i] = str2; } } textview.setText("" ); } }); } public boolean onCreateOptionsMenu (Menu paramMenu) { getMenuInflater().inflate(2131492864 , paramMenu); return true ; } public boolean onOptionsItemSelected (MenuItem paramMenuItem) { return (paramMenuItem.getItemId() == 2131034176 ) ? true : super .onOptionsItemSelected(paramMenuItem); } public static class PlaceholderFragment extends Fragment { public View onCreateView (LayoutInflater param1LayoutInflater, ViewGroup param1ViewGroup, Bundle param1Bundle) { return param1LayoutInflater.inflate(2130903064 , param1ViewGroup, false ); } } }
输入字符进行校验,符合条件的,就把这个字符串几位数进行操作之后取反,写个脚本跑一下
1 2 3 4 5 6 7 8 9 s = 'dd2940c04462b4dd7c450528835cca15' s = list(s) s = [ord(x) for x in s] s[2 ] = (s[2 ] + s[3 ] - 50 ) s[4 ] = (s[2 ] + s[5 ] - 48 ) s[30 ] = (s[31 ] + s[9 ] - 48 ) s[14 ] = (s[27 ] + s[28 ] - 97 ) s.reverse() print('' .join([chr(x) for x in s]))
出了flag{59acc538825054c7de4b26440c0999dd}
lucky guy 下载下来的结果是个X86-64的ELF,发现F5失败
得,那就分析汇编,发现是一个输入数字,然后取随机数出flag的
找到出flag的逻辑,都不用打patch,直接手动分析就是了
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 unsigned __int64 get_flag () { unsigned int v0; char v1; signed int i; signed int j; __int64 s; char v6; unsigned __int64 v7; v7 = __readfsqword(0x28 u); v0 = time(0L L); srand(v0); for ( i = 0 ; i <= 4 ; ++i ) { switch ( rand() % 200 ) { case 1 : puts ("OK, it's flag:" ); memset (&s, 0 , 0x28 uLL); strcat ((char *)&s, f1); strcat ((char *)&s, &f2); printf ("%s" , &s); break ; case 2 : printf ("Solar not like you" ); break ; case 3 : printf ("Solar want a girlfriend" ); break ; case 4 : v6 = 0 ; s = 'fo`guci'; strcat (&f2, (const char *)&s); break ; case 5 : for ( j = 0 ; j <= 7 ; ++j ) { if ( j % 2 == 1 ) v1 = *(&f2 + j) - 2 ; else v1 = *(&f2 + j) - 1 ; *(&f2 + j) = v1; } break ; default : puts ("emmm,you can't find flag 23333" ); break ; } } return __readfsqword(0x28 u) ^ v7; }
f1可以直接找到,写个脚本出f2
1 2 3 4 5 6 7 8 9 10 11 s = 'fo`guci' s = list(s) s = [ord(x) for x in s] s.reverse() for i in range(8 ): if i%2 ==1 : s[i] -= 2 else : s[i] -= 1 f1 = 'GXY{do_not_' print(f1 + '' .join([chr(x) for x in s]))
出结果GXY{do_not_hate_me}
rsa 下载下来是一个key一个enc,rsa算法就是要去找e,d,还有欧拉函数
key里面是一个base64的公钥,enc打不开,估计是加密后的字节串,有了公钥key,而且长度不算长,就可以带入到factordb.com
里面去找一下因数分解,然后求欧拉函数
1 2 3 4 5 6 import base64N = 'MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+/AvKr1rzQczdAgMBAAE=' N = base64.b64decode(N) N = [hex(x)[2 :].zfill(2 ) for x in N] print('0x' +'' .join(N))
key = 0x303c300d06092a864886f70d0101010500032b003028022100c0332c5c64ae47182f6c1c876d42336910545a58f7eefefc0bcaaf5af341ccdd0203010001
查到了因式分解的结果
7246255757203408838535614667498219793647193424559346880212407078558298027963762366749937521991103661174290022755026478321354431589 * 3^6 * 7 * 53 * 70957 * 277198451
欧拉函数可以出来了
phi = 0x1b0ae025206ee6e222bc368d42f8eed88d062df5ab5f7cc8d9bcca82519cbbdd8dc1354991b61e95e1109843ececeb5954dd14e0c086175c7aedeb8ace00L
然后就是求phi关于65537的逆元,就是我们的d
d = gmpy.invert(65537, phi)
得到d = 0x6bdf061f1331506dde814a5a543d0b056806ae6ebc1d3a7737978f7828753e3099b58c0adbe3ce3db07bb1e7c2c1904dd7e7cdd07c2a6825cf78218ca01
得到了d之后只需要对密文进行 $$ cipher^{d} % N=plain $$ 然后就是读取文件enc
转化为hex了
1 2 3 4 5 c = '' with open('rsa\\41c4e672-98c5-43e5-adf4-49d75db307e4\\output\\flag.enc' , 'rb' ) as f: c = f.read() c = [hex(x)[2 :].zfill(2 ) for x in c] print('0x' +'' .join(c))
c = 0x4196c0594a5e000a96b878b67cd724795b13a8f2ca54da06d0f19c28be689b62
然后就是pow(c, d, N)
,结果是0x10b2ee66d8c3be7d67bbeb85060700e9e4f598f627f746931aadb7a7bc17db0d573267c99c8e326e5e8458b63794ccc20493d26bfc0d147028808b91a6c0
???这根本不是可以解出来的字符串啊
用在线rsa
加解密出来也完全不是什么东西啊
得,网上找了下在线公钥分析,发现公钥解析错了,不能直接用我的方法直接从base64来解析,他这个还有固定格式的
拖进http://tool.chacuo.net/cryptrsakeyparse
里面,得到
n = C0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
分解得到 285960468890451637935629440372639283459
和304008741604601924494328155975272418463
然后就是算欧拉函数phi = 81176168860169991027846870170527607562179635470395365333547868786951080991441L
求出逆元d = 0xb378155840fb2b8fbdd869db5b7e91994f1ece256ee1175ec2c2bd3a4a795ad1
最后解密还得靠python的rsa
模块来对文件进行解密,其实这个最难不是解密,是配置gmpy2的环境,嗨,说多了都是泪啊,windows下我现在还没配好
1 2 3 4 5 6 7 8 9 10 11 12 13 import rsaimport gmpy2n = 0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD e = 0x10001 p = 285960468890451637935629440372639283459 q = 304008741604601924494328155975272418463 phi = 81176168860169991027846870170527607562179635470395365333547868786951080991441 d = 0xb378155840fb2b8fbdd869db5b7e91994f1ece256ee1175ec2c2bd3a4a795ad1 privKey = rsa.PrivateKey(n, e, d, p, q) with open('./flag.enc' , 'rb' ) as f: content = f.read() print(rsa.decrypt(content, privKey))
最后flagflag{decrypt_256}
这不应该是crypto题吗……
CrackRTF 记事本图标的exe,x86平台,拖进IDA,找到main函数逻辑
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 int main_0 () { DWORD v0; DWORD v1; CHAR pass2; int v4; CHAR s; BYTE pass1; memset (&pass1, 0 , 0x104 u); memset (&s, 0 , 0x104 u); v4 = 0 ; printf ("pls input the first passwd(1): " ); scanf ("%s" , &pass1); if ( strlen ((const char *)&pass1) != 6 ) { printf ("Must be 6 characters!\n" ); ExitProcess(0 ); } v4 = atoi((const char *)&pass1); if ( v4 < 100000 ) ExitProcess(0 ); strcat ((char *)&pass1, "@DBApp" ); v0 = strlen ((const char *)&pass1); j_sha1(&pass1, v0, &s); if ( !_strcmpi(&s, "6E32D0943418C2C33385BC35A1470250DD8923A9" ) ) { printf ("continue...\n\n" ); printf ("pls input the first passwd(2): " ); memset (&pass2, 0 , 0x104 u); scanf ("%s" , &pass2); if ( strlen (&pass2) != 6 ) { printf ("Must be 6 characters!\n" ); ExitProcess(0 ); } strcat (&pass2, (const char *)&pass1); memset (&s, 0 , 0x104 u); v1 = strlen (&pass2); j_getMd5((BYTE *)&pass2, v1, &s); if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e" , &s) ) { if ( !(unsigned __int8)sub_40100F(&pass2) ) { printf ("Error!!\n" ); ExitProcess(0 ); } printf ("bye ~~\n" ); } } return 0 ; }
看了一下逻辑,大概是对第一个字符串加盐hash,然后成功了之后拼到第二个字符串上面,我居然没查到这个hash和md5,只能暴力破解了
1 2 3 4 5 6 7 8 import hashlibsalt = '@DBApp' for i in range(100000 , 1000000 ): data = str(i)+salt hash_sha1 = hashlib.sha1(data.encode()) if hash_sha1.hexdigest().upper() == '6E32D0943418C2C33385BC35A1470250DD8923A9' : print(data)
爆出来第一个是123321,第二个继续爆,发现不是数字,直接查
~!3a@0123321@DBApp
出来了,然而不对???
继续跟进去看看这个第三个判断函数
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 char __cdecl sub_4014D0 (LPCSTR lpString) { LPCVOID lpBuffer; DWORD NumberOfBytesWritten; DWORD nNumberOfBytesToWrite; HGLOBAL hResData; HRSRC hResInfo; HANDLE hFile; hFile = 0 ; hResData = 0 ; nNumberOfBytesToWrite = 0 ; NumberOfBytesWritten = 0 ; hResInfo = FindResourceA(0 , (LPCSTR)0x65 , "AAA" ); if ( !hResInfo ) return 0 ; nNumberOfBytesToWrite = SizeofResource(0 , hResInfo); hResData = LoadResource(0 , hResInfo); if ( !hResData ) return 0 ; lpBuffer = LockResource(hResData); sub_401005(lpString, (int )lpBuffer, nNumberOfBytesToWrite); hFile = CreateFileA("dbapp.rtf" , 0x10000000 u, 0 , 0 , 2u , 0x80 u, 0 ); if ( hFile == (HANDLE)-1 ) return 0 ; if ( !WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, 0 ) ) return 0 ; CloseHandle(hFile); return 1 ; }
就是从程序本身的一个区段里面取出数据,同刚才的数据进行xor
得到flag写入在dbapp.rtf
里面,然后也懒得继续跟了,直接打开文件,出flag
Flag{N0_M0re_Free_Bugs}
pyre 下载下来是个pyc文件,直接uncompiler 反编译
uncompyle6.exe a.pyc > a.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 print 'Welcome to Re World!' print 'Your input1 is your flag~' l = len(input1) for i in range(l): num = ((input1[i] + i) % 128 + 128 ) % 128 code += num for i in range(l - 1 ): code[i] = code[i] ^ code[(i + 1 )] print codecode = ['\x1f' , '\x12' , '\x1d' , '(' , '0' , '4' , '\x01' , '\x06' , '\x14' , '4' , ',' , '\x1b' , 'U' , '?' , 'o' , '6' , '*' , ':' , '\x01' , 'D' , ';' , '%' , '\x13' ]
是个根本跑不起来的py2,而且这个code += num
操作我是有点醉的,不晓得他是啥意思,我在python2/3里面都试过了一下,没啥用,报错,就猜他是code[i] += num
((a+b) % p + c) % p = (a + (b+c) % p) % p
可以优化一下里面的取余那一步
num = ((input1[i] + i) % 128 + 128) % 128 = (input1[i] + i) % 128
(假定flag的长度不超多128)
而这个ascii
最多有126个字符,那就好办了啊,写个脚本跑一下就出来了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import stringtable = [ord(x) for x in string.printable] code = ['\x1f' , '\x12' , '\x1d' , '(' , '0' , '4' , '\x01' , '\x06' , '\x14' , '4' , ',' , '\x1b' , 'U' , '?' , 'o' , '6' , '*' , ':' , '\x01' , 'D' , ';' , '%' , '\x13' ] code = [ord(x) for x in code] for i in range(len(code)-2 , -1 , -1 ): code[i] ^= code[i+1 ] for i in range(len(code)): code[i] -= i if code[i] not in table or code[i] <= 10 : code[i] += 128 print(code) code = [chr(x) for x in code] print('' .join(code))
GWHT{Just_Re_1s_Ha66y!}
younger driver 拖进PEID查壳,是个UPX的壳,脱壳机脱了,是个32位exe
主要函数逻辑比较清晰,改名后如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int main_0 () { HANDLE v1; HANDLE hObject; j_inputFlag(); ::hObject = CreateMutexW(0 , 0 , 0 ); j_strcpy(input_dest, input_flag); hObject = CreateThread(0 , 0 , StartAddress, 0 , 0 , 0 ); v1 = CreateThread(0 , 0 , sub_41119F, 0 , 0 , 0 ); CloseHandle(hObject); CloseHandle(v1); while ( indexer != -1 ) ; j_compare(); CloseHandle(::hObject); return 0 ; }
然后startAddress
函数是用于变换的,最后的compare是用于比较变换后的flag和data是否相同
但是我电脑上没有MSVCRT100D.dll
跑不起来,于是只好静态分析他的变换函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 char *__cdecl func1 (int *input_flag, int *indexer) { char *result; char chr; chr = *(input_flag + indexer); if ( (chr < 'a' || chr > 'z' ) && (chr < 'A' || chr > 'Z' ) ) exit (0 ); if ( chr < 'a' || chr > 'z' ) { result = data[0 ]; *(input_flag + indexer) = data[0 ][*(input_flag + indexer) - 0x26 ]; } else { result = data[0 ]; *(input_flag + indexer) = data[0 ][*(input_flag + indexer) - 0x60 ]; } return result; }
他这个data就是键盘密码表,算法简而言之就是大写变小写小写变大写然后按照键盘顺序来加密
写个脚本爆破一下
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 import stringtable = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm' + '\0' data = 'TOiZiZtOrYaToUwPnToBsOaOapsyS' def decry (data ): ret = [] for i in data: idx = table.find(i) if i.islower(): ret.append(chr(idx + 0x60 )) else : ret.append(chr(idx + 0x26 )) return '' .join(ret) def encry (data:str ): ret = list(data) for i in range(len(data)): if data[i].isupper(): idx = ord(data[i]) - 0x26 else : idx = ord(data[i]) - 0x60 ret[i] = table[idx] return '' .join(ret) flag = '' for i in range(len(data)): for j in string.ascii_letters: if (encry(j) == data[i]): flag += j print(flag) e = encry(flag) print(e)
解出来flag是dhGsGsDhCeJdHfAiXdHwKhJhJIKEk
,但是交了一下,居然不对……
可惜跑不了,不能debug,让我装一个msvcrt100d.dll
看看能不能调出来,好家伙还加了反调试,他会检测你的进程列表里有没有od
和ida
之类的东西,但是我可用x32dbg啊
只是没有ida在旁边我比较难定位罢了,把这个给patch掉就好得多
patch完成,然后直接用ida调试我看看到底发生了什么
然后就发现调不通,还有一个栈顶指针错误,OD里面跟到这儿也直接卡死,硬给patch直接报错,淦
看看多线程到底说了啥
得,问题就在这,有个互斥锁,等锁,变换,然后减一,又等锁,淦
出了,完整脚本如下
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 import stringtable = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm' + '\0' data = 'TOiZiZtOrYaToUwPnToBsOaOapsyS' def encry (data:str ): ret = list(data) for i in range(len(data)): if data[i].isupper(): idx = ord(data[i]) - 0x26 else : idx = ord(data[i]) - 0x60 ret[i] = table[idx] return '' .join(ret) flag = '' for i in range(len(data)): for j in string.ascii_letters: if (encry(j) == data[i]): flag += j mutex = 0 for i in range(len(flag)): if mutex == 0 : print(data[i], end='' ) mutex = 1 else : print(flag[i], end='' ) mutex = 0
ThisisthreadofwindowshahaIsES
,最后一位会变成\0
,影响不大,反正最后一位都会变成结束符,应该是多解,但是怎么交都交不对,随后看了下网上的wp,原来预设是E,比赛的时候最后一位什么都是对的,但是这个平台只是设置了E,淦
相册 提示是个病毒,不要安装到手机里,下载下来居然还有系统报毒,有点东西
是个手机apk,用dex2jar反编译然后用jd
打开看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static int sendMailByJavaMail (String paramString1, String paramString2, String paramString3) { if (debug) return 1 ; Mail mail = new Mail(C2.MAILUSER, C2.MAILPASS); mail.set_host("smtp.163.com" ); mail.set_port("25" ); mail.set_debuggable(true ); mail.set_to(new String[] { paramString1 }); mail.set_from(C2.MAILFROME); mail.set_subject(paramString2); mail.setBody(paramString3); try { if (mail.send()) { Log.i("IcetestActivity" , "Email was sent successfully." ); return 1 ; } } catch (Exception exception) { Log.e("MailApp" , "Could not send email" , exception); return 1 ; } Log.i("IcetestActivity" , "Email was sent failed." ); return 1 ; }
然后取C2里面找找
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 public class C2 { public static final String CANCELNUMBER = "%23%2321%23" ; public static final String MAILFROME; public static final String MAILHOST = "smtp.163.com" ; public static final String MAILPASS; public static final String MAILSERVER = Base64.decode(NativeMethod.m()); public static final String MAILUSER = Base64.decode(NativeMethod.m()); public static final String MOVENUMBER = "**21*121%23" ; public static final String PORT = "25" ; public static final String date = "2115-11-1" ; public static final String phoneNumber; static { MAILPASS = Base64.decode(NativeMethod.pwd()); MAILFROME = Base64.decode(NativeMethod.m()); phoneNumber = Base64.decode(NativeMethod.p()); } }
然后去NativeMethod
1 2 3 4 5 6 7 8 9 10 package com.net.cn;public class NativeMethod { public static native String m () ; public static native String p () ; public static native String pwd () ; }
得,是个外部方法,用apktools解压一下,找到so文件,拖进IDA
进入m方法,看见一个base64字符串,出结果
1 2 3 4 5 6 7 8 9 10 11 12 .text:00000C80 Java_com_net_cn_NativeMethod_m ; DATA XREF: LOAD:00000174↑o .text:00000C80 ; __unwind { .text:00000C80 PUSH {R3,LR} .text:00000C82 LDR R2, [R0] .text:00000C84 LDR R1, =(aMtgymtg0njuxmj_0 - 0xC8E) .text:00000C86 MOVS R3, #0x29C .text:00000C8A ADD R1, PC ; "MTgyMTg0NjUxMjVAMTYzLmNvbQ==" .text:00000C8C LDR R3, [R2,R3] .text:00000C8E BLX R3 .text:00000C90 POP {R3,PC} .text:00000C90 ; End of function Java_com_net_cn_NativeMethod_m .text:00000C90
18218465125@163.com
2019红帽杯 easyRE 是个elf,用wsl跑起来啥都不弹出啊
通过字符串查找大法找到关键函数,然后从print都没有得情况来看,应该是strip过了
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 signed __int64 sub_4009C6 () { char *v0; char *v1; __int64 input_len; signed __int64 result; unsigned __int64 v4; __int64 v5; __int64 v6; __int64 v7; __int64 v8; __int64 v9; __int64 v10; __int64 v11; __int64 v12; __int64 v13; __int64 v14; __int64 v15; int i; char data[39 ]; char input[32 ]; int v19; char v20; char v21; char v22; char v23; unsigned __int64 v24; v24 = __readfsqword(0x28 u); data[0 ] = 'I' ; data[1 ] = 'o' ; data[2 ] = 'd' ; data[3 ] = 'l' ; data[4 ] = '>' ; data[5 ] = 'Q' ; data[6 ] = 'n' ; data[7 ] = 'b' ; data[8 ] = '(' ; data[9 ] = 'o' ; data[10 ] = 'c' ; data[11 ] = 'y' ; data[12 ] = '' ; data[13 ] = 'y' ; data[14 ] = '.' ; data[15 ] = 'i' ; data[16 ] = '' ; data[17 ] = 'd' ; data[18 ] = '`' ; data[19 ] = '3' ; data[20 ] = 'w' ; data[21 ] = '}' ; data[22 ] = 'w' ; data[23 ] = 'e' ; data[24 ] = 'k' ; data[25 ] = '9' ; data[26 ] = '{' ; data[27 ] = 'i' ; data[28 ] = 'y' ; data[29 ] = '=' ; data[30 ] = '~' ; data[31 ] = 'y' ; data[32 ] = 'L' ; data[33 ] = '@' ; data[34 ] = 'E' ; data[35 ] = 'C' ; memset (input, 0 , sizeof (input)); v19 = 0 ; v20 = 0 ; v0 = input; sub_4406E0(0L L, input, 37L L); v20 = 0 ; v1 = input; LODWORD(input_len) = strlen ((const __m128i *)input); if ( input_len == 0x24 ) { for ( i = 0 ; ; ++i ) { v1 = input; LODWORD(v4) = strlen ((const __m128i *)input); if ( i >= v4 ) break ; if ( (unsigned __int8)(input[i] ^ i) != data[i] ) { result = 0xFFFFFFFE LL; goto LABEL_13; } } print("continue!" ); memset (&v21, 0 , 0x40 uLL); v23 = 0 ; v0 = &v21; sub_4406E0(0L L, &v21, 64L L); v22 = 0 ; v1 = &v21; LODWORD(v5) = strlen ((const __m128i *)&v21); if ( v5 == 39 ) { v6 = transf2((__int64)&v21); v7 = transf2(v6); v8 = transf2(v7); v9 = transf2(v8); v10 = transf2(v9); v11 = transf2(v10); v12 = transf2(v11); v13 = transf2(v12); v14 = transf2(v13); v15 = transf2(v14); v0 = fool; v1 = (char *)v15; if ( !(unsigned int )sub_400360(v15, fool) ) { print("You found me!!!" ); v1 = "bye bye~" ; print("bye bye~" ); } result = 0L L; } else { result = 0xFFFFFFFD LL; } } else { result = 0xFFFFFFFF LL; } LABEL_13: if ( __readfsqword(0x28 u) != v24 ) sub_444020(v1, v0); return result; }
其中这个off_6CC090
是可以无数次base64解码最后获取到一篇文章https://bbs.pediy.com/thread-254172.htm
讲的是如何挖坑,啊,那么我岂不是……淦
跟进这个transf1
来看看,淦哦全是mm128,看的一脸懵逼,动态调试一下看看,原来是判断字符串长度的
然后就是构造一个输入了,亦或一下就出来了
Info:The first four chars are flag
???什么迷惑玩意,然后就是第二个输入,跟了一下,是循环base64之后要等于这个网址,怎么有种强烈的上当受骗的感觉
试试提交一下这个玩意,不对,我就很纳闷了……完全是被耍了啊
看看writeUP
,原来fini
段还藏着代码,找到main_fake
下面一个函数,进去就是关键算法
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 __int64 __fastcall sub_400D35 (__int64 a1, __int64 a2) { __int64 v2; __int64 result; unsigned __int64 v4; unsigned int *v5; signed int i; int v7; unsigned __int64 v8; v8 = __readfsqword(0x28 u); v2 = 0L L; for ( v5 = (unsigned int *)((unsigned int )sub_43FD20(0L L) - (unsigned int )qword_6CEE38); SHIDWORD(v5) <= 1233 ; ++HIDWORD(v5) ) { v2 = (unsigned int )v5; sub_40F790((unsigned int )v5); sub_40FE60(); sub_40FE60(); LODWORD(v5) = (unsigned __int64)sub_40FE60() ^ 0x98765432 ; } v7 = (signed int )v5; if ( ((unsigned __int8)v5 ^ data[0 ]) == 'f' && (HIBYTE(v7) ^ (unsigned __int8)MEMORY[0x6CC0A3 ]) == 'g' ) { for ( i = 0 ; i <= 24 ; ++i ) { v2 = (unsigned __int8)(data[i] ^ *((_BYTE *)&v7 + i % 4 )); sub_410E90(v2); } } v4 = __readfsqword(0x28 u); result = v4 ^ v8; if ( v4 != v8 ) sub_444020(v2, a2); return result; }
跟不出个啥玩意,只知道最开始的是flag,前面对V5也有个对比,然后构造一下还原出完整的flag,我始终找不到进入这个for函数的方法,无论输入什么,只能静态分析,v5/v7是干啥的也不清楚,如果能直接分析的话就好多了
1 2 3 4 5 6 7 8 9 10 11 12 13 data = [ 0x40 , 0x35 , 0x20 , 0x56 , 0x5D , 0x18 , 0x22 , 0x45 , 0x17 , 0x2F , 0x24 , 0x6E , 0x62 , 0x3C , 0x27 , 0x54 , 0x48 , 0x6C , 0x24 , 0x6E , 0x72 , 0x3C , 0x32 , 0x45 , 0x5B ] key= 'flag' key = list(key) key = [ord(x) for x in key] for i in range(len(key)): key[i] ^= data[i] for i in range(len(data)): data[i] ^= key[i % 4 ] print('' .join([chr(x) for x in data]))
出flagflag{Act1ve_Defen5e_Test}
好坑啊,花了我一天的时间
BJDCTF JustRE 拖进IDA,通过寻找字符串找到关键函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 BOOL __stdcall DialogFunc (HWND hWnd, UINT a2, WPARAM a3, LPARAM a4) { CHAR String; if ( a2 != 272 ) { if ( a2 != 273 ) return 0 ; if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 ) { sprintf (&String, aD, ++click_time); if ( click_time == 19999 ) { sprintf (&String, aBjdDD2069a4579, 19999 , 0 ); SetWindowTextA(hWnd, &String); return 0 ; } SetWindowTextA(hWnd, &String); return 0 ; } EndDialog(hWnd, (unsigned __int16)a3); } return 1 ; }
点击次数到了19999
就会弹出flag?让我试试这个flag,出了???什么鬼,上面的题这么坑,这个题这么简单,居然排在上面的题目后面
SUCTF2019 signin 是个x86_64的elf,直觉告诉我这种一般都不好搞,虽然只有为数不多的函数
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 __int64 __fastcall main (__int64 a1, char **a2, char **a3) { char n; char e; char m; char c; char input; char v9; unsigned __int64 v10; v10 = __readfsqword(0x28 u); puts ("[sign in]" ); printf ("[input your flag]: " , a2); __isoc99_scanf("%99s" , &input); sub_96A(&input, &v9); __gmpz_init_set_str(&c, "ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35" , 16L L); __gmpz_init_set_str(&m, &v9, 16L L); __gmpz_init_set_str(&n, "103461035900816914121390101299049044413950405173712170434161686539878160984549" , 10L L); __gmpz_init_set_str(&e, "65537" , 10L L); __gmpz_powm((__int64)&m, (__int64)&m, (__int64)&e, (__int64)&n); if ( (unsigned int )__gmpz_cmp(&m, &c) ) puts ("GG!" ); else puts ("TTTTTTTTTTql!" ); return 0L L; }
难不成是考察gmpz库的辨认?看这个加密算法有点像是rsa
已知 $$ n=0Xe4bcdf0332b194a4c28376b1a3c18bf8604a4dc3efe363e00708c402d510e9e5\ e = 0X10001\ c = 0Xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35 $$ 求m,而$m=c^d % n$
直接分解p=282164587459512124844245113950593348271
和q=366669102002966856876605669837014229419
然后求得欧拉函数phi = (p-1)*(q-1)
,d = gmpy2.invert(65537, phi)
,得到d
求m = pow(c, d, n)
,解得m = 0x73756374667b50776e5f405f68756e647265645f79656172737d
转化一下就出来了suctf{Pwn_@_hundred_years}
V&N2020 StrangeCPP 是个64位exe,吸取上次教训,不能忽略fini函数
然后果然找到了个假flag,然后有个特殊的段00cfg
,进去也不知道是干什么的,淦,又是心灵感应题
找一下wp,原来是最开始main_fake在push数据的时候有可疑数据,跟进去
找到关键函数,动态调一下看看参数是啥
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 __int64 sub_7FF61FD83580 () { __int64 *v0; signed __int64 i; __int64 result; __int64 v3; int v4; int j; __int64 v6; v0 = &v3; for ( i = 82 i64; i; --i ) { *(_DWORD *)v0 = 0xCCCCCCCC ; v0 = (__int64 *)((char *)v0 + 4 ); } v6 = -2 i64; sub_7FF61FD810AA(&unk_7FF61FD97033); result = sub_7FF61FD81384((unsigned int )key); v4 = result; if ( (_DWORD)result == 0x242EE21A && key <= 0xDE02EF ) { for ( j = 0 ; j < 17 ; ++j ) { putchar ((unsigned __int8)(key ^ data[j])); result = (unsigned int )(j + 1 ); } } return result; }
第一次没满足条件,跟进去的话key是8,跑一下看看,发现初步了解过,于是猜测最后一位是}
得到key是64,然后就能够得到flagflag{MD5(theNum)}
猜num是就是key就是64,然后跑'64'和'@'
的MD5都不对,然后进上面的函数跟一下,大概就是要解出这个方程
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 signed __int64 __fastcall solve_it (int key) { __int64 *v1; signed __int64 i; signed __int64 result; __int64 v4; int v5; int v6; unsigned int v7; int input; input = key; v1 = &v4; for ( i = 82 i64; i; --i ) { *(_DWORD *)v1 = -858993460 ; v1 = (__int64 *)((char *)v1 + 4 ); } sub_1400110AA(&unk_140027033); v5 = input >> 12 ; v6 = input << 8 ; v7 = (input << 8 ) ^ (input >> 12 ); v7 *= 291 ; if ( v7 ) result = v7; else result = 987 i64; return result; }
要我们找到input是啥这里只涉及到v7,直接暴力求解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import hashlibdata = [ 0x26 , 0x2C , 0x21 , 0x27 , 0x3B , 0x0D , 0x04 , 0x75 , 0x68 , 0x34 , 0x28 , 0x25 , 0x0E , 0x35 , 0x2D , 0x69 , 0x3D ] for i in range(len(data)): data[i] ^= 64 print('' .join([chr(x) for x in data])) result = 0x242EE21A def enc (x ): return (0x123 *(((x << 8 ) ^ (x >> 12 ))&0xffffffff )) & 0xffffffff for x in range(0xDE02EF +1 ): if enc(x) == result: print('flag {}' .format(hashlib.md5(str(x).encode()).hexdigest().lower())) break
e10adc3949ba59abbe56e057f20f883e
出了
ACTF 2020 EasyRE 里面好多个几乎一样的文件,最外面那个是x86的exe,打不开,然后查壳是个UPX,上脱壳机
主函数非常清晰,希望不要是假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 37 38 39 40 41 42 43 44 int __cdecl main (int argc, const char **argv, const char **envp) { char idx[12 ]; int v5; int v6; int v7; __int16 input; char v9; char v10; char v11; int v12; int v13; int v14; char v15; int i; __main(); idx[0 ] = 42 ; idx[1 ] = 70 ; idx[2 ] = 39 ; idx[3 ] = 34 ; idx[4 ] = 78 ; idx[5 ] = 44 ; idx[6 ] = 34 ; idx[7 ] = 40 ; idx[8 ] = 73 ; idx[9 ] = 63 ; idx[10 ] = 43 ; idx[11 ] = 64 ; printf ("Please input:" ); scanf ("%s" , &input); if ( (_BYTE)input != 65 || HIBYTE(input) != 67 || v9 != 84 || v10 != 70 || v11 != 123 || v15 != 125 ) return 0 ; v5 = v12; v6 = v13; v7 = v14; for ( i = 0 ; i <= 11 ; ++i ) { if ( idx[i] != _data_start__[*((char *)&v5 + i) - 1 ] ) return 0 ; } printf ("You are correct!" ); return 0 ; }
写个脚本出了,不知道是不是真的
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 idx = [0 ]*12 idx[0 ] = 42 ; idx[1 ] = 70 ; idx[2 ] = 39 ; idx[3 ] = 34 ; idx[4 ] = 78 ; idx[5 ] = 44 ; idx[6 ] = 34 ; idx[7 ] = 40 ; idx[8 ] = 73 ; idx[9 ] = 63 ; idx[10 ] = 43 ; idx[11 ] = 64 ; data_start = [0x7e , 0x7D , 0x7C , 0x7B , 0x7A , 0x79 , 0x78 , 0x77 , 0x76 , 0x75 , 0x74 , 0x73 , 0x72 , 0x71 , 0x70 , 0x6F , 0x6E , 0x6D , 0x6C , 0x6B , 0x6A , 0x69 , 0x68 , 0x67 , 0x66 , 0x65 , 0x64 , 0x63 , 0x62 , 0x61 , 0x60 , 0x5F , 0x5E , 0x5D , 0x5C , 0x5B , 0x5A , 0x59 , 0x58 , 0x57 , 0x56 , 0x55 , 0x54 , 0x53 , 0x52 , 0x51 , 0x50 , 0x4F , 0x4E , 0x4D , 0x4C , 0x4B , 0x4A , 0x49 , 0x48 , 0x47 , 0x46 , 0x45 , 0x44 , 0x43 , 0x42 , 0x41 , 0x40 , 0x3F , 0x3E , 0x3D , 0x3C , 0x3B , 0x3A , 0x39 , 0x38 , 0x37 , 0x36 , 0x35 , 0x34 , 0x33 , 0x32 , 0x31 , 0x30 , 0x2F , 0x2E , 0x2D , 0x2C , 0x2B , 0x2A , 0x29 , 0x28 , 0x27 , 0x26 , 0x25 , 0x24 , 0x23 , 0x20 , 0x21 , 0x22 , 0x00 ] flag = [] for i in range(len(idx)): d = data_start.index(idx[i]) d += 1 flag.append(d) print('' .join([chr(x) for x in flag]))
ACTF{U9X_1S_W6@T?}
出了
GUET-CTF re ELF-X86-64文件,加载开来只有几个函数,库函数都见不到,看参数应该是加了UPX的壳,脱了
关键函数
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 _BOOL8 __fastcall sub_4009AE (char *input) { if ( 1629056 * *input != 166163712 ) return 0L L; if ( 6771600 * input[1 ] != 731332800 ) return 0L L; if ( 3682944 * input[2 ] != 357245568 ) return 0L L; if ( 10431000 * input[3 ] != 1074393000 ) return 0L L; if ( 3977328 * input[4 ] != 489211344 ) return 0L L; if ( 5138336 * input[5 ] != 518971936 ) return 0L L; if ( 7532250 * input[7 ] != 406741500 ) return 0L L; if ( 5551632 * input[8 ] != 294236496 ) return 0L L; if ( 3409728 * input[9 ] != 177305856 ) return 0L L; if ( 13013670 * input[10 ] != 650683500 ) return 0L L; if ( 6088797 * input[11 ] != 298351053 ) return 0L L; if ( 7884663 * input[12 ] != 386348487 ) return 0L L; if ( 8944053 * input[13 ] != 438258597 ) return 0L L; if ( 5198490 * input[14 ] != 249527520 ) return 0L L; if ( 4544518 * input[15 ] != 445362764 ) return 0L L; if ( 3645600 * input[17 ] != 174988800 ) return 0L L; if ( 10115280 * input[16 ] != 981182160 ) return 0L L; if ( 9667504 * input[18 ] != 493042704 ) return 0L L; if ( 5364450 * input[19 ] != 257493600 ) return 0L L; if ( 13464540 * input[20 ] != 767478780 ) return 0L L; if ( 5488432 * input[21 ] != 312840624 ) return 0L L; if ( 14479500 * input[22 ] != 1404511500 ) return 0L L; if ( 6451830 * input[23 ] != 316139670 ) return 0L L; if ( 6252576 * input[24 ] != 619005024 ) return 0L L; if ( 7763364 * input[25 ] != 372641472 ) return 0L L; if ( 7327320 * input[26 ] != 373693320 ) return 0L L; if ( 8741520 * input[27 ] != 498266640 ) return 0L L; if ( 8871876 * input[28 ] != 452465676 ) return 0L L; if ( 4086720 * input[29 ] != 208422720 ) return 0L L; if ( 9374400 * input[30 ] == 515592000 ) return 5759124 * input[31 ] == 719890500 ; return 0L L; }
每一位挨着挨着求就是了,想想能不能用正则表达式来自动化一下
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 import retext = """ _BOOL8 __fastcall sub_4009AE(char *input) { if ( 1629056 * *input != 166163712 ) return 0LL; if ( 6771600 * input[1] != 731332800 ) return 0LL; if ( 3682944 * input[2] != 357245568 ) return 0LL; if ( 10431000 * input[3] != 1074393000 ) return 0LL; if ( 3977328 * input[4] != 489211344 ) return 0LL; if ( 5138336 * input[5] != 518971936 ) return 0LL; if ( 7532250 * input[7] != 406741500 ) return 0LL; if ( 5551632 * input[8] != 294236496 ) return 0LL; if ( 3409728 * input[9] != 177305856 ) return 0LL; if ( 13013670 * input[10] != 650683500 ) return 0LL; if ( 6088797 * input[11] != 298351053 ) return 0LL; if ( 7884663 * input[12] != 386348487 ) return 0LL; if ( 8944053 * input[13] != 438258597 ) return 0LL; if ( 5198490 * input[14] != 249527520 ) return 0LL; if ( 4544518 * input[15] != 445362764 ) return 0LL; if ( 3645600 * input[17] != 174988800 ) return 0LL; if ( 10115280 * input[16] != 981182160 ) return 0LL; if ( 9667504 * input[18] != 493042704 ) return 0LL; if ( 5364450 * input[19] != 257493600 ) return 0LL; if ( 13464540 * input[20] != 767478780 ) return 0LL; if ( 5488432 * input[21] != 312840624 ) return 0LL; if ( 14479500 * input[22] != 1404511500 ) return 0LL; if ( 6451830 * input[23] != 316139670 ) return 0LL; if ( 6252576 * input[24] != 619005024 ) return 0LL; if ( 7763364 * input[25] != 372641472 ) return 0LL; if ( 7327320 * input[26] != 373693320 ) return 0LL; if ( 8741520 * input[27] != 498266640 ) return 0LL; if ( 8871876 * input[28] != 452465676 ) return 0LL; if ( 4086720 * input[29] != 208422720 ) return 0LL; if ( 9374400 * input[30] == 515592000 ) return 5759124 * input[31] == 719890500; return 0LL; } """ text = text.split('\n' )[1 ::2 ] flag = [] for i in text: if i[:2 ] == 'if' : numbers1 = re.findall("\d+ \*" , i)[0 ][:-2 ] numbers2 = re.findall("= \d+" , i)[0 ][2 :] ch = int(numbers2) / int(numbers1) flag.append(ch) flag.append(719890500 /5759124 ) flag = [int(x) for x in flag] print('' .join([chr(x) for x in flag]))
出了flag{e65421110b0a3099a1c039337}
,然后一交,不对,长度还是有点问题有个没匹配到,是input[6],而且还俩移位的
对flag改一下位置flag{e_65421110ba03099a1c039337}
,交了一下成功,是多解,但是这个平台还是判错,只能找wp了,淦
最后一位默认是1
FlareOn4 login 是个html,打开之后就是一个login登录框,有点东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!DOCTYPE Html /> <html > <head > <title > FLARE On 2017</title > </head > <body > <input type ="text" name ="flag" id ="flag" value ="Enter the flag" /> <input type ="button" id ="prompt" value ="Click to check the flag" /> <script type ="text/javascript" > document .getElementById("prompt" ).onclick = function ( ) { var flag = document .getElementById("flag" ).value; var rotFlag = flag.replace(/[a-zA-Z]/g , function (c ) {return String .fromCharCode((c <= "Z" ? 90 : 122 ) >= (c = c.charCodeAt(0 ) + 13 ) ? c : c - 26 );}); if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) { alert("Correct flag!" ); } else { alert("Incorrect flag, rot again" ); } } </script > </body > </html >
一个加密,懒得逆算法直接爆破算了,反正咱也看不懂js
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 import stringimport execjsjscode = """ function encry(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);} """ jsc = execjs.compile(jscode) out = "PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" table = string.printable def encry (s:str ): return jsc.call("encry" , s) flag = [] for i in range(len(out)): if out[i] in string.ascii_letters: for letter in table: if encry(letter) == out[i]: flag.append(letter) print(letter, end=' ' ) break else : flag.append('_' ) else : flag.append(out[i]) print('' .join(flag)) print([ord(x) for x in flag]) print(len(out)) print(len(flag))
出flagClientSideLoginsAreEasy@flare-on.com
,其中的S还被换成了9
,后面猜了一下出了
V&N 2020 CSRe 是个.Net文件,放在dnspy
下面跑一堆乱码,完全没法看,用de4dot
看看
关键函数
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 using System;using System.Security.Cryptography;using System.Text;internal sealed class Class3 { public string method_0 (string string_0, string string_1 ) { string text = string .Empty; char [] array = string_0.ToCharArray(); char [] array2 = string_1.ToCharArray(); int num = (array.Length < array2.Length) ? array.Length : array2.Length; for (int i = 0 ; i < num; i++) { text += (int )(array[i] ^ array2[i]); } return text; } public static string smethod_0 (string string_0 ) { byte [] bytes = Encoding.UTF8.GetBytes(string_0); byte [] array = SHA1.Create().ComputeHash(bytes); StringBuilder stringBuilder = new StringBuilder(); foreach (byte b in array) { stringBuilder.Append(b.ToString("X2" )); } return stringBuilder.ToString(); } private static void Main (string [] args ) { if (!Class1.smethod_1()) { return ; } bool flag = true ; Class3 @class = new Class3(); string str = Console.ReadLine(); if (Class3.smethod_0("3" + str + "9" ) != "B498BFA2498E21325D1178417BEA459EB2CD28F8" ) { flag = false ; } string text = Console.ReadLine(); string string_ = Class3.smethod_0("re" + text); string text2 = @class.method_0(string_, "63143B6F8007B98C53CA2149822777B3566F9241" ); for (int i = 0 ; i < text2.Length; i++) { if (text2[i] != '0' ) { flag = false ; } } if (flag) { Console.WriteLine("flag{" + str + text + "}" ); } } }
函数还是比较清楚,先查sha1B498BFA2498E21325D1178417BEA459EB2CD28F8
,是314159
然后就是查被xor 之后的sha1 了,他这句text2[i] != '0'
看的我很迷,然后就查原文,查到是return
所以flag就是flag{1415turn}
BJDCTF easy 打开一看
1 2 3 4 5 6 7 8 9 10 11 12 int __cdecl main (int argc, const char **argv, const char **envp) { time_t v4; struct tm *v5 ; __main(); time(&v4); v5 = localtime(&v4); puts ("Can you find me?\n" ); system("pause" ); return 0 ; }
???看了一下汇编也没啥玩意啊?
看了一下main函数上面那个有点蹊跷
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 int ques () { int v0; int result; int v2[50 ]; int v3; int v4; int v5; int v6; int v7; int v8; int v9; int v10; int v11; int v12; int j; __int64 v14; int v15; int v16; int i; v3 = 0x7FFA7E31 ; v4 = 0x224FC ; v5 = 0x884A4239 ; v6 = 0x22A84 ; v7 = 0x84FF235 ; v8 = 0x3FF87 ; v9 = 0x88424233 ; v10 = 0x23185 ; v11 = 0x7E4243F1 ; v12 = 0x231FC ; for ( i = 0 ; i <= 4 ; ++i ) { memset (v2, 0 , sizeof (v2)); v16 = 0 ; v15 = 0 ; v0 = *(&v4 + 2 * i); LODWORD(v14) = *(&v3 + 2 * i); HIDWORD(v14) = v0; while ( SHIDWORD(v14) > 0 || v14 >= 0 && (_DWORD)v14 ) { v2[v16++] = ((SHIDWORD(v14) >> 31 ) ^ (((unsigned __int8)(SHIDWORD(v14) >> 31 ) ^ (unsigned __int8)v14) - (unsigned __int8)(SHIDWORD(v14) >> 31 )) & 1 ) - (SHIDWORD(v14) >> 31 ); v14 /= 2L L; } for ( j = 50 ; j >= 0 ; --j ) { if ( v2[j] ) { if ( v2[j] == 1 ) { putchar ('*' ); ++v15; } } else { putchar (' ' ); ++v15; } if ( !(v15 % 5 ) ) putchar (32 ); } result = putchar (10 ); } return result; }
但是查找交叉引用缺啥也没有,改一下eip看看直接执行这个函数,执行结果是这个
1 2 3 4 5 6 7 8 9 10 * * * ***** * * ***** ***** * * ***** * * * * * * * * * * * * * * * * * * ** * ***** ***** * *** * * ***** *** * * * * * * * * * * * ** * * * * * * * ** * * * * ***** * * ***** * * * ***** * * * * * ***** * * ***** ***** * * ***** * * * * * * * * * * * * * * * * * * ** * ***** ***** * *** * * ***** *** * * * * * * * * * * * ** * * * * * * * ** * * * * ***** * * ***** * * * ***** * *
是HACKIT4FUN
,出了