この大会は2020/10/26 14:30(JST)~2020/10/28 14:30(JST)に開催されました。
今回もチームで参戦。結果は7964点で314チーム中44位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (Misc)
ルールのページにフラグが書いてある画像があった。
RaziCTF{S0_iT_b3G1Ns}
720 (Misc)
添付ファイルの圧縮ファイルにはdllが6個入っている。その内、printui.dllは解凍でき、展開されたThe Flag You Need.txtにフラグが書かれていた。
RaziCTF{5pl17_4nd_j01n}
chasing a lock (Android Security)
Bytecode Viewerでデコンパイルする。
package com.example.razictf_2; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; class MainActivity$2 implements OnClickListener { // $FF: synthetic field final MainActivity this$0; MainActivity$2(MainActivity var1) { this.this$0 = var1; } public void onClick(View var1) { TextView var2 = (TextView)this.this$0.findViewById(2131165190); int var3 = Integer.parseInt(var2.getText().toString()); if (var3 != 0 && var3 >= 0) { --var3; String var4 = (new switcher()).run(var3); if (var4 != null) { ((TextView)this.this$0.findViewById(2131165187)).setText(var4); } var2.setText(String.valueOf(var3)); } else { var2.setText("0"); } } } package com.example.razictf_2; public class switcher { public String run(int var1) { if (var1 == 0) { a1 var2 = new a1(); StringBuilder var3 = new StringBuilder(); var3.append(" "); var3.append(var2.run(var1)); String var4 = var3.toString(); a2 var8 = new a2(); System.out.println(var8.run(var1)); StringBuilder var5 = new StringBuilder(); var5.append(var4); var5.append(var8.run(var1)); String var9 = var5.toString(); a3 var6 = new a3(); StringBuilder var10 = new StringBuilder(); var10.append(var9); var10.append(var6.run(var1)); var9 = var10.toString(); a4 var7 = new a4(); var10 = new StringBuilder(); var10.append(var9); var10.append(var7.run(var1)); var4 = var10.toString(); a5 var11 = new a5(); var5 = new StringBuilder(); var5.append(var4); var5.append(var11.run(var1)); return var5.toString(); } else { return null; } } } package com.example.razictf_2; import android.util.Base64; public class a1 { public String run(int var1) { String var2 = "Vm0wd2QyUXlVWGxWV0d4V1YwZDRWMVl3WkRSV01WbDNXa1JTVjAxV2JETlhhMUpUVmpBeFYySkVUbGhoTVVwVVZtcEJlRll5U2tWVWJHaG9UVlZ3VlZadGNFSmxSbGw1VTJ0V1ZXSkhhRzlVVmxaM1ZsWmFkR05GU214U2JHdzFWVEowVjFaWFNraGhSemxWVm14YU0xWnNXbUZqVmtaMFVteFNUbUpGY0VwV2JURXdZVEZrU0ZOclpHcFRSVXBZV1ZSR2QyRkdjRmRYYlVaclVsUkdWbFpYZUZOVWJVWTJVbFJHVjJFeVVYZFpla3BIWXpGT2RWVnRhRk5sYlhoWFZtMXdUMVF3TUhoalJscFlZbFZhY2xWcVFURlNNV1J5VjJ4T1ZXSlZjRWRaTUZaM1ZqSktWVkpZWkZkaGExcFlXa1ZhVDJNeFpITmhSMnhUVFcxb1dsWXhaRFJpTWtsNVZtNU9WbUpHV2xSWmJGWmhZMVphZEdSSFJrNVNiRm93V2xWYVQxWlhTbFpqUldSYVRVWmFNMVpxU2t0V1ZrcFpXa1p3VjFKV2NIbFdWRUpoVkRKT2MyTkZhR3BTYXpWWVZXcE9iMkl4V1hoYVJGSldUVlZzTlZaWE5VOVhSMHBJVld4c1dtSkdXbWhaTW5oWFkxWkdWVkpzVGs1V01VbzFWbXBKTVdFeFdYZE5WVlpUWVRGd1YxbHJXa3RUUmxweFVtMUdVMkpWYkRaWGExcHJZVWRGZUdOSE9WZGhhMHBvVmtSS1QyUkdTbkpoUjJoVFlYcFdlbGRYZUc5aU1XUkhWMjVTVGxOSFVuTlZha0p6VGtaVmVXUkhkRmhTTUhCSlZsZDRjMWR0U2tkWGJXaGFUVzVvV0ZsNlJsZGpiSEJIV2tkc1UySnJTbUZXTW5oWFdWWlJlRmRzYUZSaVJuQlpWbXRXZDFZeGJISlhhM1JVVW14d2VGVnRNVWRWTWtwV1lrUmFXR0V4Y0hKWlZXUkdaVWRPU0U5V1pHaGhNSEJ2Vm10U1MxUXlVa2RUYmtwaFVtMW9jRlpxU205bGJHUllaVWM1YVUxcmJEUldNV2h2V1ZaS1IxTnVRbFZXTTFKNlZHdGFZVk5IVWtoa1JtUnBWbGhDU1ZacVNqUlZNV1IwVTJ0a1dHSlhhR0ZVVnpWdlYwWnJlRmRyWkZkV2EzQjZWa2R6TVZZd01WWmlla1pYWWxoQ1RGUnJXbEpsUm1SellVWlNhVkp1UW5oV1YzaHJWVEZzVjFWc1dsaGlWVnBQVkZaYWQyVkdWWGxrUkVKWFRWWndlVmt3V25kWFIwVjRZMFJPV21FeVVrZGFWM2hIWTIxS1IxcEhiRmhTVlhCS1ZtMTBVMU14VlhoWFdHaFlZbXhhVmxsclpHOWpSbHB4VTIwNWJHSkhVbGxhVldNMVlWVXhjbUpFVWxkTmFsWlVWa2Q0YTFOR1ZuTlhiRlpYVFRGS05sWkhlR0ZXTWxKSVZXdG9hMUl5YUhCVmJHaENaREZhYzFwRVVtcE5WMUl3VlRKMGExZEhTbGhoUjBaVlZucFdkbFl3V25KbFJtUnlXa1prVjJFelFqWldhMlI2VFZaa1IxTnNXbXBTVjNoWVdXeG9RMVJHVW5KWGJFcHNVbTFTZWxsVldsTmhSVEZ6VTI1b1YxWjZSVEJhUkVaclVqSktTVlJ0YUZOaGVsWlFWa1phWVdReVZrZFdXR3hyVWtWS1dGUldXbmRsVm10M1YyNWtXRkl3VmpSWk1GSlBWMjFGZVZWclpHRldNMmhJV1RJeFMxSXhjRWhpUm1oVFZsaENTMVp0TVRCVk1VMTRWbGhvV0ZkSGFGbFpiWGhoVm14c2NscEhPV3BTYkhCNFZUSXdOV0pIU2toVmJHeGhWbGROTVZsV1ZYaGpiVXBGVld4a1RtRnNXbFZXYTJRMFlURk9SMVp1VGxoaVJscFlXV3RvUTFkV1draGxSMFpYVFd4S1NWWlhkRzloTVVwMFZXczVWMkZyV2t4Vk1uaHJWakZhZEZKdGNFNVdNVWwzVmxSS01HRXhaRWhUYkdob1VqQmFWbFp1Y0Zka2JGbDNWMjVLYkZKdFVubFhhMXByVmpKRmVsRnFXbGRoTWxJMlZGWmFXbVF3TVZkWGJXeHNZVEZ3V1ZkWGVHOVJNVkpIVlc1S1dHSkZjSE5WYlRGVFpXeHNWbGRzVG1oV2EzQXhWVmMxYjFZeFdYcGhTRXBYVmtWYWVsWnFSbGRqTVdSellVZHNWMVp1UWpaV01XUXdXVmRSZVZaclpGZFhSM2h5Vld0V1MxZEdVbGRYYm1Sc1ZteHNOVnBWYUd0WFIwcEhZMFpvV2sxSFVuWldNbmhoVjBaV2NscEhSbGRXTVVwUlZsZHdTMUl4U1hsU2EyaHBVbXMxY0ZsVVFuZE5iRnAwVFZSQ1ZrMVZNVFJXVm1oelZtMUZlVlZzV2xwaVdGSXpXVlZhVjJSSFZrWmtSM0JUWWtoQ05GWnJZM2RPVm1SSFYyNU9hbEp0ZUdGVVZWcFdUVlpzVjFaWWFHcGlWWEJHVmxkNGExUnRSbk5YYkZaWVZtMVJNRlY2Um1GamF6VlhZa1pLYVZKc2NGbFhWM1JoWkRGa1YxZHJhR3RTTUZwdlZGZHpNV1ZzV1hsT1ZrNW9UVlZzTlZsVmFFTldiVXBJWVVWT1lWSkZXbWhaZWtaM1VsWldkR05GTlZkTlZXd3pWbXhTUzAxSFJYaGFSV2hVWWtkb2IxVnFRbUZXYkZwMFpVaGtUazFXY0hsV01qRkhZV3hhY21ORVFtRlNWMUYzVm1wS1MyTnNUbkpoUm1SVFRUSm9iMVpyVWt0U01WbDRWRzVXVm1KRlNsaFZiRkpYVjFaYVIxbDZSbWxOVjFKSVdXdGFWMVZzWkVoaFJsSlZWbTFTVkZwWGVITldiR1J6Vkcxb1UxWkZXalpXVkVreFlqRlplRmRZY0ZaaVIyaFpWbTE0ZDFsV2NGWlhiWFJyVm10d2VsWnRNWE5XTVVsNllVUldWMDFYVVhkWFZtUlNaVlphY2xwR1pHbGlSWEI1VmxkMFYxTXlTWGhpUm14cVVsZFNjMVp0ZUV0bGJGcDBUVVJXV0ZJd2NFaFpNRnB2VjJzeFNHRkZlRmROYm1ob1ZqQmFWMk5zY0VoU2JHUk9UVzFvU2xZeFVrcGxSazE0VTFob2FsSlhVbWhWYlhNeFYwWlpkMVpyZEU1aVJuQXdXVEJXYTFkc1dYZFdhbEpYWWtkb2RsWXdXbXRUUjBaSFYyeHdhVmRIYUc5V2JURTBZekpPYzFwSVNtdFNNMEpVV1d0YWQwNUdXbGhOVkVKT1VteHNORll5TlU5aGJFcFlZVVpvVjJGck5WUldSVnB6VmxaR1dXRkdUbGRoTTBJMlZtdGtORmxXVlhsVGExcFlWMGhDV0Zac1duZFNNVkY0VjJ0T1ZtSkZTbFpVVlZGM1VGRTlQUT09"; for(var1 = 0; var1 < 20; ++var1) { var2 = new String(Base64.decode(var2.getBytes(), 0)); } return var2; } }
20回base64デコードする。
enc = 'Vm0wd2QyUXlVWGxWV0d4V1YwZDRWMVl3WkRSV01WbDNXa1JTVjAxV2JETlhhMUpUVmpBeFYySkVUbGhoTVVwVVZtcEJlRll5U2tWVWJHaG9UVlZ3VlZadGNFSmxSbGw1VTJ0V1ZXSkhhRzlVVmxaM1ZsWmFkR05GU214U2JHdzFWVEowVjFaWFNraGhSemxWVm14YU0xWnNXbUZqVmtaMFVteFNUbUpGY0VwV2JURXdZVEZrU0ZOclpHcFRSVXBZV1ZSR2QyRkdjRmRYYlVaclVsUkdWbFpYZUZOVWJVWTJVbFJHVjJFeVVYZFpla3BIWXpGT2RWVnRhRk5sYlhoWFZtMXdUMVF3TUhoalJscFlZbFZhY2xWcVFURlNNV1J5VjJ4T1ZXSlZjRWRaTUZaM1ZqSktWVkpZWkZkaGExcFlXa1ZhVDJNeFpITmhSMnhUVFcxb1dsWXhaRFJpTWtsNVZtNU9WbUpHV2xSWmJGWmhZMVphZEdSSFJrNVNiRm93V2xWYVQxWlhTbFpqUldSYVRVWmFNMVpxU2t0V1ZrcFpXa1p3VjFKV2NIbFdWRUpoVkRKT2MyTkZhR3BTYXpWWVZXcE9iMkl4V1hoYVJGSldUVlZzTlZaWE5VOVhSMHBJVld4c1dtSkdXbWhaTW5oWFkxWkdWVkpzVGs1V01VbzFWbXBKTVdFeFdYZE5WVlpUWVRGd1YxbHJXa3RUUmxweFVtMUdVMkpWYkRaWGExcHJZVWRGZUdOSE9WZGhhMHBvVmtSS1QyUkdTbkpoUjJoVFlYcFdlbGRYZUc5aU1XUkhWMjVTVGxOSFVuTlZha0p6VGtaVmVXUkhkRmhTTUhCSlZsZDRjMWR0U2tkWGJXaGFUVzVvV0ZsNlJsZGpiSEJIV2tkc1UySnJTbUZXTW5oWFdWWlJlRmRzYUZSaVJuQlpWbXRXZDFZeGJISlhhM1JVVW14d2VGVnRNVWRWTWtwV1lrUmFXR0V4Y0hKWlZXUkdaVWRPU0U5V1pHaGhNSEJ2Vm10U1MxUXlVa2RUYmtwaFVtMW9jRlpxU205bGJHUllaVWM1YVUxcmJEUldNV2h2V1ZaS1IxTnVRbFZXTTFKNlZHdGFZVk5IVWtoa1JtUnBWbGhDU1ZacVNqUlZNV1IwVTJ0a1dHSlhhR0ZVVnpWdlYwWnJlRmRyWkZkV2EzQjZWa2R6TVZZd01WWmlla1pYWWxoQ1RGUnJXbEpsUm1SellVWlNhVkp1UW5oV1YzaHJWVEZzVjFWc1dsaGlWVnBQVkZaYWQyVkdWWGxrUkVKWFRWWndlVmt3V25kWFIwVjRZMFJPV21FeVVrZGFWM2hIWTIxS1IxcEhiRmhTVlhCS1ZtMTBVMU14VlhoWFdHaFlZbXhhVmxsclpHOWpSbHB4VTIwNWJHSkhVbGxhVldNMVlWVXhjbUpFVWxkTmFsWlVWa2Q0YTFOR1ZuTlhiRlpYVFRGS05sWkhlR0ZXTWxKSVZXdG9hMUl5YUhCVmJHaENaREZhYzFwRVVtcE5WMUl3VlRKMGExZEhTbGhoUjBaVlZucFdkbFl3V25KbFJtUnlXa1prVjJFelFqWldhMlI2VFZaa1IxTnNXbXBTVjNoWVdXeG9RMVJHVW5KWGJFcHNVbTFTZWxsVldsTmhSVEZ6VTI1b1YxWjZSVEJhUkVaclVqSktTVlJ0YUZOaGVsWlFWa1phWVdReVZrZFdXR3hyVWtWS1dGUldXbmRsVm10M1YyNWtXRkl3VmpSWk1GSlBWMjFGZVZWclpHRldNMmhJV1RJeFMxSXhjRWhpUm1oVFZsaENTMVp0TVRCVk1VMTRWbGhvV0ZkSGFGbFpiWGhoVm14c2NscEhPV3BTYkhCNFZUSXdOV0pIU2toVmJHeGhWbGROTVZsV1ZYaGpiVXBGVld4a1RtRnNXbFZXYTJRMFlURk9SMVp1VGxoaVJscFlXV3RvUTFkV1draGxSMFpYVFd4S1NWWlhkRzloTVVwMFZXczVWMkZyV2t4Vk1uaHJWakZhZEZKdGNFNVdNVWwzVmxSS01HRXhaRWhUYkdob1VqQmFWbFp1Y0Zka2JGbDNWMjVLYkZKdFVubFhhMXByVmpKRmVsRnFXbGRoTWxJMlZGWmFXbVF3TVZkWGJXeHNZVEZ3V1ZkWGVHOVJNVkpIVlc1S1dHSkZjSE5WYlRGVFpXeHNWbGRzVG1oV2EzQXhWVmMxYjFZeFdYcGhTRXBYVmtWYWVsWnFSbGRqTVdSellVZHNWMVp1UWpaV01XUXdXVmRSZVZaclpGZFhSM2h5Vld0V1MxZEdVbGRYYm1Sc1ZteHNOVnBWYUd0WFIwcEhZMFpvV2sxSFVuWldNbmhoVjBaV2NscEhSbGRXTVVwUlZsZHdTMUl4U1hsU2EyaHBVbXMxY0ZsVVFuZE5iRnAwVFZSQ1ZrMVZNVFJXVm1oelZtMUZlVlZzV2xwaVdGSXpXVlZhVjJSSFZrWmtSM0JUWWtoQ05GWnJZM2RPVm1SSFYyNU9hbEp0ZUdGVVZWcFdUVlpzVjFaWWFHcGlWWEJHVmxkNGExUnRSbk5YYkZaWVZtMVJNRlY2Um1GamF6VlhZa1pLYVZKc2NGbFhWM1JoWkRGa1YxZHJhR3RTTUZwdlZGZHpNV1ZzV1hsT1ZrNW9UVlZzTlZsVmFFTldiVXBJWVVWT1lWSkZXbWhaZWtaM1VsWldkR05GTlZkTlZXd3pWbXhTUzAxSFJYaGFSV2hVWWtkb2IxVnFRbUZXYkZwMFpVaGtUazFXY0hsV01qRkhZV3hhY21ORVFtRlNWMUYzVm1wS1MyTnNUbkpoUm1SVFRUSm9iMVpyVWt0U01WbDRWRzVXVm1KRlNsaFZiRkpYVjFaYVIxbDZSbWxOVjFKSVdXdGFWMVZzWkVoaFJsSlZWbTFTVkZwWGVITldiR1J6Vkcxb1UxWkZXalpXVkVreFlqRlplRmRZY0ZaaVIyaFpWbTE0ZDFsV2NGWlhiWFJyVm10d2VsWnRNWE5XTVVsNllVUldWMDFYVVhkWFZtUlNaVlphY2xwR1pHbGlSWEI1VmxkMFYxTXlTWGhpUm14cVVsZFNjMVp0ZUV0bGJGcDBUVVJXV0ZJd2NFaFpNRnB2VjJzeFNHRkZlRmROYm1ob1ZqQmFWMk5zY0VoU2JHUk9UVzFvU2xZeFVrcGxSazE0VTFob2FsSlhVbWhWYlhNeFYwWlpkMVpyZEU1aVJuQXdXVEJXYTFkc1dYZFdhbEpYWWtkb2RsWXdXbXRUUjBaSFYyeHdhVmRIYUc5V2JURTBZekpPYzFwSVNtdFNNMEpVV1d0YWQwNUdXbGhOVkVKT1VteHNORll5TlU5aGJFcFlZVVpvVjJGck5WUldSVnB6VmxaR1dXRkdUbGRoTTBJMlZtdGtORmxXVlhsVGExcFlWMGhDV0Zac1duZFNNVkY0VjJ0T1ZtSkZTbFpVVlZGM1VGRTlQUT09' for i in range(20): enc = enc.decode('base64') print enc
★var4 = " RaziCTF"
package com.example.razictf_2; public class a2 { private int fromHex(char var1) { if (var1 >= '0' && var1 <= '9') { return var1 - 48; } else { byte var2 = 65; if (var1 < 'A' || var1 > 'F') { var2 = 97; if (var1 < 'a' || var1 > 'f') { throw new IllegalArgumentException(); } } return var1 - var2 + 10; } } private char toHex(int var1) { if (var1 >= 0 && var1 <= 15) { return "0123456789ABCDEF".charAt(var1); } else { throw new IllegalArgumentException(); } } public String run(int var1) { return this.xorHex("787d6c7f2c352b2c", "313333376d616e73313333376861"); } public String xorHex(String var1, String var2) { char[] var3 = new char[var1.length()]; byte var4 = 0; int var5; for(var5 = 0; var5 < var3.length; ++var5) { var3[var5] = this.toHex(this.fromHex(var1.charAt(var5)) ^ this.fromHex(var2.charAt(var5))); } StringBuilder var6 = new StringBuilder(); int var8; for(var5 = var4; var5 < (new String(var3)).length(); var5 = var8) { var2 = new String(var3); var8 = var5 + 2; var6.append((char)Integer.parseInt(var2.substring(var5, var8), 16)); } StringBuilder var7 = new StringBuilder(); var7.append("{"); var7.append(var6.toString().trim()); return var7.toString(); } }
上記を実行するだけでよい。
var1 = '787d6c7f2c352b2c' var2 = '313333376d616e73313333376861' var3 = '' for i in range(len(var1)): var3 += hex(int(var1[i], 16) ^ int(var2[i], 16))[2:] var6 = '' for i in range(0, len(var3), 2): var6 += chr(int(var3[i:i+2], 16)) var7 = '{' + var6 print var7
★{IN_HATE_ →var9 = " RaziCTF{IN_HATE_"
package com.example.razictf_2; public class a3 { public String run(int var1) { var1 = var1 % 100000 / 2; StringBuilder var2 = new StringBuilder(); var2.append(var1 - var1); var2.append("F"); return var2.toString(); } }
★0F →var9 = " RaziCTF{IN_HATE_0F"
package com.example.razictf_2; public class a4 { public String run(int var1) { return "_RUNN"; } }
★_RUNN →var4 = " RaziCTF{IN_HATE_0F_RUNN"
package com.example.razictf_2; import java.security.MessageDigest; public class a5 { public String run(int var1) { String[] var2 = new String[]{"!", "%", "="}; String[] var3 = new String[]{"a", "b", "N"}; String[] var4 = new String[]{"1", "G", "2"}; String[] var5 = new String[]{"_", "%", "="}; String var6 = "0"; String[] var7 = new String[]{"C", "q", "3"}; String[] var8 = new String[]{"4", "K", "("}; String[] var9 = new String[]{"5", "J", "K"}; System.out.println("a"); String var12; for(var1 = 0; var1 < 3; ++var1) { for(int var10 = 0; var10 < 3; var6 = var12) { int var11 = 0; var12 = var6; String var48; String[] var49; for(var49 = var5; var11 < 3; var12 = var48) { int var13 = 0; String[] var52; for(var48 = var12; var13 < 3; var7 = var52) { int var14 = 0; for(var52 = var7; var14 < 3; var8 = var7) { int var15 = 0; var7 = var8; for(var8 = var52; var15 < 3; ++var15) { for(int var16 = 0; var16 < 3; ++var16) { for(int var17 = 0; var17 < 3; var3 = var52) { int var18 = 0; var52 = var3; String[] var19 = var2; String[] var20; for(var20 = var49; var18 < 3; var4 = var2) { StringBuilder var42 = new StringBuilder(); var42.append(var19[var1]); var42.append(var52[var10]); var42.append(var4[var11]); var42.append(var20[var13]); var42.append((new String[]{"A", "L", "D"})[var14]); var42.append((new String[]{"R", "0", "$"})[var15]); var42.append(var8[var16]); var42.append(var7[var17]); var42.append(var9[var18]); String var43 = var42.toString(); StringBuilder var40 = new StringBuilder(); var40.append(var43); var40.append("}"); String var21 = var40.toString(); System.out.println(var21); String var47; label174: { boolean var28; label173: { Exception var50; label222: { Exception var10000; label170: { Exception var44; label169: { Exception var46; label213: { byte[] var22; StringBuilder var23; int var24; label167: { label214: { MessageDigest var45; try { var45 = MessageDigest.getInstance("MD5"); } catch (Exception var39) { var44 = var39; break label214; } try { var45.update(var21.getBytes()); var22 = var45.digest(); var23 = new StringBuilder(); } catch (Exception var38) { var44 = var38; break label214; } try { var24 = var22.length; break label167; } catch (Exception var37) { var44 = var37; } } var49 = var4; var46 = var44; break label213; } int var25 = 0; var3 = var4; label155: while(true) { boolean var10001; if (var25 >= var24) { var2 = var3; var47 = var48; var3 = var3; try { var28 = var23.toString().equals("b469f80f05290ed415770ea56e69a476"); break label173; } catch (Exception var29) { var10000 = var29; var10001 = false; break label170; } } var49 = var3; String var41 = var48; label216: { String var26; try { var26 = Integer.toHexString(var22[var25] & 255); } catch (Exception var36) { var10000 = var36; var10001 = false; break label216; } var47 = var48; var5 = var3; while(true) { var49 = var5; var41 = var47; int var27; try { var27 = var26.length(); } catch (Exception var35) { var10000 = var35; var10001 = false; break; } if (var27 >= 2) { var41 = var47; var47 = var47; var3 = var5; try { var23.append(var26); } catch (Exception var30) { var10000 = var30; var10001 = false; break label170; } ++var25; var3 = var5; var48 = var41; continue label155; } StringBuilder var51; try { var51 = new StringBuilder(); } catch (Exception var34) { var44 = var34; var6 = var47; var2 = var5; break label169; } var41 = var47; var47 = var47; var3 = var5; try { var51.append(var41); } catch (Exception var33) { var10000 = var33; var10001 = false; break label170; } var47 = var41; var3 = var5; try { var51.append(var26); } catch (Exception var32) { var10000 = var32; var10001 = false; break label170; } var47 = var41; var3 = var5; try { var26 = var51.toString(); } catch (Exception var31) { var10000 = var31; var10001 = false; break label170; } var47 = var41; } } var46 = var10000; var48 = var41; break; } } var2 = var49; var6 = var48; var44 = var46; } var47 = var6; var50 = var44; break label222; } var50 = var10000; var2 = var3; } var50.printStackTrace(); break label174; } var47 = var48; if (var28) { return var21; } } ++var18; var48 = var47; } ++var17; var49 = var20; var2 = var19; } } } ++var14; var52 = var8; } ++var13; } ++var11; } ++var10; var5 = var49; } } return "y"; } }
★そのまま実行した方が早い→!NG_L0CK5} →var5 = " RaziCTF{IN_HATE_0F_RUNN!NG_L0CK5}"
RaziCTF{IN_HATE_0F_RUNN!NG_L0CK5}
Can you see thorough the crowd? (Digital forensics)
ncで接続し、適当な文字を入力すると、base64文字列が延々出力される。よく見ると、","と","の間にPNGのBase64文字列が表示されることがわかる。
デコードすると、IHDRがRaziになっているので、その変換だけ行い、PNG画像にする。
import socket def recvuntil(s, tails): data = '' while True: for tail in tails: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('130.185.122.69', 12478)) data = recvuntil(s, ':') print data + 'a' s.sendall('a\n') data = recvuntil(s, ',') data = recvuntil(s, ',')[:-1] data = data.decode('base64') data = data[:12] + 'IHDR' + data[16:] with open('flag.png', 'wb') as f: f.write(data)
画像にはフラグが書かれていた。
RAZICTF{CORRUPT3D_IM4G3S_ARE_L0V3LY}
Culture (Steganography)
$ zsteg enc.png imagedata .. text: "+*#QRM'(\"" b1,bgr,lsb,xy .. text: "RaziCTF{i_s33_ur_4_MaN_0f_LSB_aS_W3LL}=====" b2,b,lsb,xy .. text: "UZ_yl\t z" b4,r,lsb,xy .. text: "ff3\"\"#Ffffwwww" b4,r,msb,xy .. text: ["U" repeated 8 times] b4,g,lsb,xy .. text: "322\"3\"22TB2\"" b4,g,msb,xy .. text: "UUUU3333" b4,b,lsb,xy .. text: "\"#33#\"33EDDDUUUU" b4,b,msb,xy .. text: ["U" repeated 8 times]
RaziCTF{i_s33_ur_4_MaN_0f_LSB_aS_W3LL}
Cliche (Steganography)
wavの画像受信データがあるかもしれないので、sstvのツールでデコードしてみる。
$ sstv -d enc.wav -o flag.png [sstv] Searching for calibration header... Found! [sstv] Detected SSTV mode Scottie 1 [sstv] Decoding image... [#############################################] 100% [sstv] Drawing image data... [sstv] ...Done!
flag.pngにフラグが書かれている。
RaziCTF{h0w_y0u_d0in}
Mod Is Coming (Steganography)
f1は中国人余剰定理の結果を返す。f2は最大公約数を返す。f3はinverseを返す。
secretmsg.txtの長さは画像の高さから331バイト。kを総当たりして、条件を満たすものを探す。
from PIL import Image def f1(n, a): sum = 0 prod = reduce(lambda a, b: a*b, n) for n_i, a_i in zip(n, a): p = prod // n_i sum += a_i * f3(p, n_i) * p return sum % prod def f2(a, b): if b == 0: return a else: return f2(b, a % b) def f3(a, b): b0 = b x0, x1 = 0, 1 if b == 1: return 1 while a > 1: q = a // b a, b = b, a % b x0, x1 = x1 - q * x0, x0 if x1 < 0: x1 += b0 return x1 LEN = 331 c_p = [] for i in range(10, 21): for j in range(i+1, 21): if f2(i, j) == 1: c_p.append([i, j]) ks = [] for i in range(len(c_p)): k = f1(c_p[i], [LEN, LEN * 3]) if k not in ks: ks.append(k) img = Image.open('enc.png').convert('RGB') r, g, b = img.getpixel((0, 0)) for k in ks: c1 = (f3(k-10, 251) * r) % 251 c2 = (f3(k, 251) * g) % 251 c3 = (f3(k+10, 251) * b) % 251 if c1 == c2 and c2 == c3: print '[+] k =', k break secretmsg = '' for y in range(LEN): r, g, b = img.getpixel((0, y)) c = (f3(k-10, 251) * r) % 251 secretmsg += chr(c) print secretmsg
実行結果は以下の通り。
[+] k = 201 Chaos isn't a pit. Chaos is a ladder, Many who try to climb it fail, and never get to try again, the fall breaks them. And some are given a chance to climb, but they refuse. They cling to the realm, or the gods, or love ... illusions. Only the ladder is real, the climb is all there is. RaziCTF{7h3_script_1s_d4rk_4nd_full_0f_m0ds}
末尾にフラグが書かれている。
RaziCTF{7h3_script_1s_d4rk_4nd_full_0f_m0ds}
Cryptfun (Cryptography)
substitution cipher symbolで調べたら、Betamaze alphabetであることがわかった。https://omniglot.com/conscripts/betamaze.htmを参考に復号する。
UC4NDRAWMAZ3SWITHITT00
RaziCTF{UC4NDRAWMAZ3SWITHITT00}
Ladder (Cryptography)
base32デコード、base58デコード、base62デコード、base64デコード、base85デコードの順にデコードする。
#!/usr/bin/python3 import base64 import base58 import base62 from Crypto.Util.number import * with open('enc.txt', 'r') as f: data = f.read() data = base64.b32decode(data) print(data) data = base58.b58decode(data) print(data) data = long_to_bytes(base62.decode(data.decode())) print(data) data = base64.b64decode(data) print(data) data = base64.a85decode(data) print(data)
実行結果は以下の通り。
b'3ujJnYq1YPYVouAmFC24c36quqhmGkcm5LL5mZGvs6w4mewG9Cg3jLhWJgcdMyT1EM1ZYp2cCabt6syu9oAnjLeoDkiJKgS7' b'B3ubcEe7waVuE55z96FTrO8JvfuevhFXEhXqzkWINOiIaRd4OlGLhL5jgqUXaQRwNC0CXl' b'O0lPbGM2Vz9PJUc7RVNyMFFeWVlDaSFJIzg3Yy1wQDNkWE1JLw==' b';IOlc6W?O%G;ESr0Q^YYCi!I#87c-p@3dXMI/' b'RaziCTF{w3_G0t_4ll_tHe_Ba$3s}'
RaziCTF{w3_G0t_4ll_tHe_Ba$3s}
Cross Onion Roll!!! (Cryptography)
タイトルからCross=Xとして、頭文字をとって、XORと推測。XOR Crackerでクラックしてみる。XORキーは13バイトで、最初にフラグが入っていそう。調整しながら復号してみる。
with open('cipher', 'rb') as f: ct = f.read() pre_flag = 'RaziCTF{d0nt_' key = '' for i in range(13): key += chr(ord(ct[i]) ^ ord(pre_flag[i])) pt = '' for i in range(len(ct)): pt += chr(ord(ct[i]) ^ ord(key[i%len(key)])) print pt
復号結果は以下の通り。
RaziCTF{d0nt_r3pe4T_kEy_1N_X0R} You cannot be buried in obscurity , you are exposed upon a grand theater to the view of the world . If your actions are upright and benevolent , be assured they will augment your power and happiness.
RaziCTF{d0nt_r3pe4T_kEy_1N_X0R}
A rEal gAME (Cryptography)
Rail Fence Cipher。https://www.geocachingtoolbox.com/index.php?lang=en&page=railFenceCipherで復号する。
RratDLD{TED_4_O0VU_PA4LU_DCA_SRIAU_I1YH3$}
Bifid Cipher。https://www.geocachingtoolbox.com/index.php?lang=en&page=bifidCipherでkeyに"RaziCTF"を指定して復号する。
RaziCTF{ITS_4_G0OD_ST4RT_XTO_STUDY_C1PH3$}