第一题easyre
ida查壳直接看
flag{this_Is_a_EaSyRe}
第二题reverse1
定位到Str2{hello_world}
根据
for ( j = 0; ; ++j ) { v8 = j; v2 = j_strlen(Str2); if ( v8 > v2 ) break; if ( Str2[j] == 'o' ) Str2[j] = '0'; }
把o换成0
flag{hell0_w0rld}
第三题reverse2
ELF即linux 下可执行文件
先用ida看看
找到{hacking_for_fun}
定位到关键代码
for ( i = 0; i <= strlen(&flag); ++i ) { if ( *(&flag + i) == 'i' || *(&flag + i) == 'r' ) *(&flag + i) = '1'; }
把i或者r换成1
直接换flag{hack1ng_fo1_fun}
第四题内涵的软件
直接看
v6 = 5; v5 = "DBAPP{49d3c93df25caad81232130f3d2ebfad}"; while ( v6 >= 0 ) { printf("距离出现答案还有%d秒,请耐心等待!\n", v6); sub_40100A(); --v6; } printf( "\n" "\n" "\n" "这里本来应该是答案的,但是粗心的程序员忘记把变量写进来了,你要不逆向试试看:(Y/N)\n"); v4[0] = 1; scanf("%c", v4); if ( v4[0] == 'Y' ) { printf("OD吾爱破解或者IDA这些逆向软件都挺好的!"); result = sub_40100A(); } else { if ( v4[0] == 'N' ) printf("那没办法了,猜是猜不出的."); else printf(&byte_42501C); result = sub_40100A(); } return result;
v5十分可疑,直接flag{49d3c93df25caad81232130f3d2ebfad}
第五题新年快乐
查壳,发现UPX,直接脱壳
定位关键
__main(); strcpy(Str2, "HappyNewYear!"); Str1 = 0; memset(v6, 0, sizeof(v6)); printf("please input the true flag:"); scanf("%s", &Str1); if ( !strncmp((const char *)&Str1, Str2, strlen(Str2)) ) result = puts("this is true flag!"); else result = puts("wrong!"); return result;
Str2就是flag
flag{HappyNewYear!}
第六题xor
mac 64位
ida进
定位关键的代码
memset(__b, 0, 0x100uLL); printf("Input your flag:\n"); get_line(__b, 256LL); if ( strlen(__b) != 33 ) goto LABEL_7; for ( i = 1; i < 33; ++i ) __b[i] ^= __b[i - 1]; if ( !strncmp(__b, global, 0x21uLL) ) printf("Success"); else LABEL_7: printf("Failed"); return 0;
分析flag 33位,进入异或后和global相等
导出global
unsigned char aFK[] = { 102, 10, 107, 12, 119, 38, 79, 46, 64, 17, 120, 13, 90, 59, 85, 17, 112, 25, 70, 31, 118, 34, 77, 35, 68, 14, 103, 6, 104, 15, 71, 50, 79 };
写EXP
#include<stdio.h> #include<windows.h> #include<string.h> int main(){ char str[]={ 102, 10, 107, 12, 119, 38, 79, 46, 64, 17, 120, 13, 90, 59, 85, 17, 112, 25, 70, 31, 118, 34, 77, 35, 68, 14, 103, 6, 104, 15, 71, 50, 79 }; int i,len = 33; for(i=len-1;i>=1;i--){str[i]^=str[i-1];} puts(str); } //flag{QianQiuWanDai_YiTongJiangHu}
第七题helloword
apk逆向,准备工具jadx
定位到关键代码
package com.example.helloword; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends ActionBarActivity { /* access modifiers changed from: protected */ @Override // android.support.v7.app.ActionBarActivity, android.support.v4.app.FragmentActivity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); "flag{7631a988259a00816deda84afb29430a}".compareTo("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
直接提取flag
flag{7631a988259a00816deda84afb29430a}
第八题reverse3
ida打开
定位到关键代码
sub_41132F("please enter the flag:", v7); sub_411375("%20s", (char)Str); v3 = j_strlen(Str); v4 = (const char *)sub_4110BE(Str, v3, v14); strncpy(Destination, v4, 0x28u); v11 = j_strlen(Destination); for ( j = 0; j < v11; ++j ) Destination[j] += j; v5 = j_strlen(Destination); if ( !strncmp(Destination, Str2, v5) ) sub_41132F("rigth flag!\n", v8); else sub_41132F("wrong flag!\n", v8); return 0;
接着分享 flag给到了Str,进入了函数sub_4110BE(Str, v3, v14);处理
然后处理为v4,v4复制到Destination,Destination进行加操作,接着和Str2比较
我们发现sub_4110BE对字符串flag进行base64加密(字符特征)
Str2=“e3nifIH9b_C@n@dH”
直接写EXP
#include<stdio.h> #include<windows.h> #include<string.h> int main(){ char str[]="e3nifIH9b_C@n@dH"; int i,len = strlen(str); for(i=0;i<len;i++){str[i]-=i;} puts(str); } //e2lfbDB2ZV95b3V9 //拿着e2lfbDB2ZV95b3V9进行常规base64解密 //flag{i_l0ve_you}
第九题不一样的flag
有点像游戏,用ida打开
f5直接看,定位到
strcpy(v3, "*11110100001010000101111#"); for ( i = 0; i <= 1; ++i ) { if ( *(&v4 + i) < 0 || *(&v4 + i) > 4 ) exit(1); } if ( v8[5 * v4 - 41 + v5] == '1' ) exit(1); if ( v8[5 * v4 - 41 + v5] == '#' ) { puts("\nok, the order you enter is the flag!"); exit(0); }
首先
puts("1 up"); puts("2 down"); puts("3 left"); printf("4 right\n:");
超出1到范围直接退出
其次在数组v3种遇到1或者#直接退出,但#提示我们输入的就是flag,这是一道典型的迷宫题
根据二维数组公式结合
if ( v8[5 * v4 - 41 + v5] == '1' ) exit(1); if ( v8[5 * v4 - 41 + v5] == '#' )
假设迷宫一列5位,v4是行,v5是列
*1111 01000 01010 00010 1111#
我们这种迷宫直接手写,如果是复杂的那种要用递归写。
flag{222441144222}
第十题SimpleRev
ELF文件
定位到Decry()关键函数
unsigned __int64 Decry() { char v1; // [rsp+Fh] [rbp-51h] int v2; // [rsp+10h] [rbp-50h] int v3; // [rsp+14h] [rbp-4Ch] int i; // [rsp+18h] [rbp-48h] int v5; // [rsp+1Ch] [rbp-44h] char src[8]; // [rsp+20h] [rbp-40h] BYREF __int64 v7; // [rsp+28h] [rbp-38h] int v8; // [rsp+30h] [rbp-30h] __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF int v10; // [rsp+50h] [rbp-10h] unsigned __int64 v11; // [rsp+58h] [rbp-8h] v11 = __readfsqword(0x28u); *(_QWORD *)src = 'SLCDN'; v7 = 0LL; v8 = 0; v9[0] = 'wodah'; v9[1] = '\0'; v10 = 0; text = (char *)join(key3, v9); // key3="killshadow" strcpy(key, key1); strcat(key, src); // key="ADSFKNDCLS" v2 = 0; v3 = 0; getchar(); v5 = strlen(key); for ( i = 0; i < v5; ++i ) { if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 ) key[i] = key[v3 % v5] + 32; ++v3; } printf("Please input your flag:"); while ( 1 ) { v1 = getchar(); if ( v1 == 10 ) break; if ( v1 == 32 ) { ++v2; } else { if ( v1 <= '`' || v1 > 'z' ) { if ( v1 > '@' && v1 <= 'Z' ) { str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97; ++v3; } } else { str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97; ++v3; } if ( !(v3 % v5) ) putchar(32); ++v2; } } if ( !strcmp(text, str2) ) puts("Congratulation!\n"); else puts("Try again!\n"); return __readfsqword(0x28u) ^ v11; }
text=str2 为key3,key经过变化后,与flag操作成为Str2
注意,大小端的问题,我们换成字符串的时候要注意顺序
我们直接写EXP
#include<stdio.h> #include<windows.h> #include<string.h> int main(){ char key[]="adsfkndcls"; char str2[]="killshadow"; int v5 = strlen(key); char flag[v5+1]; flag[v5] = '\0'; int i; int j = 0; for( i = 0; i < v5; ++i ){ j = 0; for( j = 0;j<10;j++) { flag[i]=str2[i]-97+26*j+39-97+key[i]; if( flag[i]<='Z'&&flag[i]>='A'||flag[i]>='a'&&flag[i]<='z') break; } } puts(flag); }
第十一题JAVA逆向
用jadx打开
package defpackage; import java.util.ArrayList; import java.util.Scanner; /* renamed from: Reverse reason: default package */ public class Reverse { public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.println("Please input the flag :"); String str = s.next(); System.out.println("Your input is :"); System.out.println(str); Encrypt(str.toCharArray()); } public static void Encrypt(char[] arr) { int[] KEY; ArrayList<Integer> Resultlist = new ArrayList<>(); for (char c : arr) { Resultlist.add(Integer.valueOf((c) +'@' ^ 32)); } ArrayList<Integer> KEYList = new ArrayList<>(); for (int i : new int[]{180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65}) { KEYList.add(Integer.valueOf(i)); } System.out.println("Result:"); if (Resultlist.equals(KEYList)) { System.out.println("Congratulations!"); } else { System.err.println("Error!"); } } }
显而易见,直接写EXP
#include<stdio.h> #include<windows.h> #include<string.h> int main(){ char enflag[]={180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65}; int len = strlen(enflag); char flag[len + 1]; flag[len] = '\0'; int i; for(i = 0; i < len; i++){ flag[i] = enflag[i]-'@'^32; } puts(flag); } //flag{This_is_the_flag_!}
第十二题[GXYCTF2019]luck_guy
定位关键代码
v5 = __readfsqword(0x28u); v0 = time(0LL); srand(v0); for ( i = 0; i <= 4; ++i ) { switch ( rand() % 200 ) { case 1: puts("OK, it's flag:"); memset(s, 0, sizeof(s)); strcat((char *)s, f1); // GXY{do_not_ strcat((char *)s, &f2); printf("%s", (const char *)s); break; case 2: printf("Solar not like you"); break; case 3: printf("Solar want a girlfriend"); break; case 4: strcpy((char *)s, "icug`of\x7F"); strcat(&f2, (const char *)s); break; case 5: for ( j = 0; j <= 7; ++j ) { if ( j % 2 == 1 ) *(&f2 + j) -= 2; else --*(&f2 + j); } break; default: puts("emmm,you can't find flag 23333"); break; }
逻辑简单,我们直接拿到上半部分GXY{do_not_
下半部分直接写EXP
#include<stdio.h> #include<windows.h> #include<string.h> int main(){ char s[]="icug`of\x7F"; int j; int len = strlen(s); for ( j = 0; j <= 7; ++j ) { if ( j % 2 == 1 ) s[j]-= 2; else s[j] -=1; } puts( s ); } //hate_me}
flag{do_not_hate_me}
第十三题刮开有奖
定位到关键代码
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4) { const char *v4; // esi const char *v5; // edi int v7[10]; // [esp+8h] [ebp-20030h] BYREF int v8; // [esp+30h] [ebp-20008h] CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF char v10[65536]; // [esp+10034h] [ebp-10004h] BYREF if ( a2 == 272 ) return 1; if ( a2 != 273 ) return 0; if ( (_WORD)a3 == 1001 ) { memset(String, 0, 0xFFFFu); GetDlgItemTextA(hDlg, 1000, String, 0xFFFF); if ( strlen(String) == 8 ) { v7[0] = 90; v7[1] = 74; v7[2] = 83; v7[3] = 69; v7[4] = 67; v7[5] = 97; v7[6] = 78; v7[7] = 72; v7[8] = 51; v7[9] = 110; v8 = 103; sub_4010F0(v7, 0, 10); memset(v10, 0, 0xFFFFu); v10[0] = String[5]; v10[2] = String[7]; v10[1] = String[6]; v4 = (const char *)sub_401000(v10, strlen(v10)); memset(v10, 0, 0xFFFFu); v10[1] = String[3]; v10[0] = String[2]; v10[2] = String[4]; v5 = (const char *)sub_401000(v10, strlen(v10)); if ( String[0] == v7[0] + 34 && String[1] == v7[4] && 4 * String[2] - 141 == 3 * v7[2] && String[3] / 4 == 2 * (v7[7] / 9) && !strcmp(v4, "ak1w") && !strcmp(v5, "V1Ax") ) { MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0); } } return 0; } if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 ) return 0; EndDialog(hDlg, (unsigned __int16)a3); return 1; }
这道题让我学会了,如果动态调试调不了,可以把代码copy下来,自己跑。
先说说思路String的后6位很简单,解base64就出来了,但前2位是要进过sub_4010F0函数变化得到的,重点就到了加密上。太多太复杂,我动态调试,结果跑不到我的断点。看到大佬的WP让我感悟到可以直接copy代码,自己跑
我们得知道加密后的v7
#include<stdio.h> void sub_7310F0(int *v7, int a2, int a3) { int v3; // eax int i; // esi int v5; // ecx int v6; // edx v3 = a3; for ( i = a2; i <= a3; a2 = i ) { v5 = i; v6 = v7[i]; if ( a2 < v3 && i < v3 ) { do { if ( v6 > v7[v3] ) { if ( i >= v3 ) break; ++i; v7[v5] = v7[v3]; if ( i >= v3 ) break; while ( v7[i] <= v6 ) { if ( ++i >= v3 ) goto LABEL_13; } if ( i >= v3 ) break; v5 = i; v7[v3] = v7[i]; } --v3; } while ( i < v3 ); } LABEL_13: v7[v3] = v6; sub_7310F0(v7, a2, i - 1); v3 = a3; ++i; } } int main() { int v7[11]; v7[0] = 90; v7[1] = 74; v7[2] = 83; v7[3] = 69; v7[4] = 67; v7[5] = 97; v7[6] = 78; v7[7] = 72; v7[8] = 51; v7[9] = 110; v7[10] = 103; sub_7310F0(v7,0,10); for ( int i = 0; i <10;i++) { printf("%c",v7[i]); } //3CEHJNSZag }
然后直接解
#include<stdio.h> #include<windows.h> #include<string.h> int main(){ char v7[11]="3CEHJNSZag"; char String[9]; String[0] = v7[0] + 34; String[1] = v7[4]; String[5]='j'; String[6]='M'; String[7]='p'; String[2]= 'W'; String[3]='P'; String[4]='1'; String[8]='\0'; puts(String); //UJWP1jMp }