2019SCTF 部分WP
本帖最后由 yechen123 于 2019-6-25 21:24 编辑题目可在xctf社区获取
strange apk
一道安卓题,直接APKIDE打开。
通过阅读代码发现
public class c
extends Application
{
private String apkFileName;
private String libPath;
protected AssetManager mAssetManager;
protected Resources mResources;
protected Resources.Theme mTheme;
private String odexPath;
private void _(byte[] paramArrayOfByte)
throws IOException
{
paramArrayOfByte = _0_(paramArrayOfByte);
Object localObject = new File(this.apkFileName);
try
{
localObject = new FileOutputStream((File)localObject);
((FileOutputStream)localObject).write(paramArrayOfByte);
((FileOutputStream)localObject).close();
return;
}
catch (IOException paramArrayOfByte)
{
throw new RuntimeException(paramArrayOfByte);
}
}
private byte[] _0_(byte[] paramArrayOfByte)
{
int i = 0;
while (i < paramArrayOfByte.length)
{
paramArrayOfByte = ((byte)("syclover".charAt(i % "syclover".length()) ^ paramArrayOfByte));
i += 1;
}
return paramArrayOfByte;
}
public byte[] __(String paramString)
throws IOException
{
paramString = getResources().getAssets().open(paramString);
byte[] arrayOfByte = new byte;
paramString.read(arrayOfByte);
return arrayOfByte;
}
protected void attachBaseContext(Context paramContext)
{
super.attachBaseContext(paramContext);
try
{
paramContext = getDir("sctf_odex", 0);
localObject = getDir("sctf_lib", 0);
this.odexPath = paramContext.getAbsolutePath();
this.libPath = ((File)localObject).getAbsolutePath();
localObject = new StringBuilder();
((StringBuilder)localObject).append(paramContext.getAbsolutePath());
((StringBuilder)localObject).append("/sctf.apk");
this.apkFileName = ((StringBuilder)localObject).toString();
paramContext = new File(this.apkFileName);
localObject = new StringBuilder();
((StringBuilder)localObject).append("apk size:");
((StringBuilder)localObject).append(paramContext.length());
Log.i("demo", ((StringBuilder)localObject).toString());
if (!paramContext.exists())
{
paramContext.createNewFile();
_(__("data"));
}
paramContext = s.invokeStaticMethod("android.app.ActivityThread", "currentActivityThread", new Class, new Object);
localObject = getPackageName();
if (Build.VERSION.SDK_INT < 19) {
paramContext = (WeakReference)((HashMap)s.getFieldOjbect("android.app.ActivityThread", paramContext, "mPackages")).get(localObject);
} else {
paramContext = (WeakReference)((ArrayMap)s.getFieldOjbect("android.app.ActivityThread", paramContext, "mPackages")).get(localObject);
}
localObject = new DexClassLoader(this.apkFileName, this.odexPath, this.libPath, (ClassLoader)s.getFieldOjbect("android.app.LoadedApk", paramContext.get(), "mClassLoader"));
s.setFieldOjbect("android.app.LoadedApk", "mClassLoader", paramContext.get(), localObject);
paramContext = new StringBuilder();
paramContext.append("classloader:");
paramContext.append(localObject);
Log.i("demo", paramContext.toString());
return;
}
catch (Exception paramContext)
{
Object localObject = new StringBuilder();
((StringBuilder)localObject).append("error:");
((StringBuilder)localObject).append(Log.getStackTraceString(paramContext));
Log.i("demo", ((StringBuilder)localObject).toString());
paramContext.printStackTrace();
}
}
该APK中隐藏着一个data文件,直接修改后缀为zip打开,data解密之后就是一个APK。
上脚本解密
i = "syclover"
f = open("data", "rb")
q = open("datas","wb")
couts = 0
c = f.read(1)
qq = 0
while (1):
uq = ord(c)^ord(i)
if (uq<=15):
q.write(("0x0"+hex(uq)))
else:
q.write((hex(uq)))
couts += 1
qq += 1
if (couts%2==0 and couts%16!=0):
q.write(' ')
if (couts%16==0):
q.write('\n')
c = f.read(1)
if c==None:
break
q.close()
f.close()
可以把datas里边的数据用winhex以二进制方式存入一个新文件,原来手动存的时候一直显示未预料到文件尾,还以为要手动修复zip,原来是自己的问题,可能是文件尾部多了一些数据,导致CRC校验出错。
最终得到一个新APK。
阅读代码。
protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2131296285);
paramBundle = (Button)findViewById(2131165218);
findViewById(2131165322);
paramBundle.setOnClickListener(new View.OnClickListener()
{
public void onClick(View paramAnonymousView)
{
paramAnonymousView = "";
Object localObject1 = "";
int i = 0;
String str = this.val$ed.getText().toString();
if (str.length() == 30)
{
while (i < 12)
{
localObject2 = new StringBuilder();
((StringBuilder)localObject2).append(paramAnonymousView);
((StringBuilder)localObject2).append(str.charAt(i));
paramAnonymousView = ((StringBuilder)localObject2).toString();
i += 1;
}
Object localObject2 = f.sctf(paramAnonymousView);
paramAnonymousView = (View)localObject1;
while (i < 30)
{
localObject1 = new StringBuilder();
((StringBuilder)localObject1).append(paramAnonymousView);
((StringBuilder)localObject1).append(str.charAt(i));
paramAnonymousView = ((StringBuilder)localObject1).toString();
i += 1;
}
if (((String)localObject2).equals("c2N0ZntXM2xjMG1l"))
{
localObject1 = new Intent();
((Intent)localObject1).putExtra("data_return", paramAnonymousView);
s.this.setResult(-1, (Intent)localObject1);
s.this.finish();
return;
}
Toast.makeText(s.this.getApplicationContext(), "something wrong", 1).show();
return;
}
Toast.makeText(s.this.getApplicationContext(), "something wrong", 1).show();
}
});
}
c2N0ZntXM2xjMG1l base64解密得到前半flag sctf{W3lc0me
protected void onActivityResult(int paramInt1, int paramInt2, Intent paramIntent)
{
TextView localTextView = (TextView)findViewById(2131165323);
Button localButton = (Button)findViewById(2131165219);
if (paramInt1 != 1) {
return;
}
if (paramInt2 == -1)
{
Object localObject1 = "";
try
{
Object localObject2 = MessageDigest.getInstance("MD5");
((MessageDigest)localObject2).update("syclover".getBytes());
localObject2 = new BigInteger(1, ((MessageDigest)localObject2).digest()).toString(16);
localObject1 = localObject2;
}
catch (Exception localException)
{
localException.printStackTrace();
}
if (f.encode(paramIntent.getStringExtra("data_return"), (String)localObject1).equals("~8t808_8A8n848r808i8d8-8w808r8l8d8}8"))
{
localTextView.setVisibility(0);
localButton.setVisibility(4);
}
else
{
Toast.makeText(getApplicationContext(), "one more step", 1).show();
}
}}
public static String encode(String paramString1, String paramString2)
{
int j = paramString1.length();
int k = paramString2.length();
StringBuilder localStringBuilder = new StringBuilder();
int i = 0;
while (i < j)
{
localStringBuilder.append(paramString1.charAt(i));
localStringBuilder.append(paramString2.charAt(i / k));
i += 1;
}
return localStringBuilder.toString();
}
~8t808_8A8n848r808i8d8-8w808r8l8d8}8取奇数得到后半flag。
最终sctf{W3lc0me~t0_An4r0id-w0rld}
creakme
ida阅读代码
int sub_402540()
{
HMODULE v0; // eax
int v1; // eax
_DWORD *v2; // eax
unsigned int ser_len; // edx
_DWORD *string; // ecx
unsigned int string_len; // ebx
char *ascc; // edi
unsigned int v7; // esi
unsigned int v8; // esi
bool v9; // cf
unsigned __int8 v10; // al
unsigned __int8 v11; // al
unsigned __int8 v12; // al
signed int v13; // esi
_BYTE *v14; // ecx
_BYTE *v15; // ecx
const char *v16; // edx
int v17; // eax
void *Memory; //
int v20; //
unsigned int v21; //
void *Dst; //
int v23; //
unsigned int v24; //
char Src; //
int v26; //
v0 = GetModuleHandleW(0);
sub_402320(v0);
sub_4024A0();
v1 = sub_402870(std::cout, "welcome to 2019 sctf");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v1, sub_402AC0);
sub_402870(std::cout, "please input your ticket:");
sub_402AF0(std::cin, &Src);
v23 = 0;
v24 = 15;
LOBYTE(Dst) = 0;
sub_401D30(&Dst, &Src, strlen(&Src));
v26 = 0;
v2 = aes(&Memory, (int)&Dst);
ser_len = strlen(aPvfqyc4ttc2uxr);
string = v2;
if ( v2 >= 16u )
string = (_DWORD *)*v2;
string_len = v2;
ascc = aPvfqyc4ttc2uxr;
v7 = v2;
if ( ser_len < string_len )
v7 = ser_len;
v9 = v7 < 4; // len - 4
v8 = v7 - 4;
if ( v9 )
{
LABEL_8:
if ( v8 == -4 )
goto LABEL_17;
}
else
{
while ( *string == *(_DWORD *)ascc )
{
++string; // +=4
ascc += 4;
v9 = v8 < 4;
v8 -= 4;
if ( v9 )
goto LABEL_8;
}
}
v9 = *(_BYTE *)string < (unsigned __int8)*ascc;
if ( *(_BYTE *)string != *ascc
|| v8 != -3
&& ((v10 = *((_BYTE *)string + 1), v9 = v10 < (unsigned __int8)ascc, v10 != ascc)
|| v8 != -2
&& ((v11 = *((_BYTE *)string + 2), v9 = v11 < (unsigned __int8)ascc, v11 != ascc)
|| v8 != -1 && (v12 = *((_BYTE *)string + 3), v9 = v12 < (unsigned __int8)ascc, v12 != ascc))) )
{
v13 = -v9 | 1;
goto LABEL_18;
}
LABEL_17:
v13 = 0;
LABEL_18:
if ( !v13 ) // v13要为0
{
if ( ser_len <= string_len )
v13 = ser_len < string_len;
else
v13 = -1;
}
if ( v21 >= 0x10 )
{
v14 = Memory;
if ( v21 + 1 >= 0x1000 )
{
v14 = (_BYTE *)*((_DWORD *)Memory - 1);
if ( (unsigned int)((_BYTE *)Memory - v14 - 4) > 0x1F )
invalid_parameter_noinfo_noreturn(v14, v21 + 36);
}
frees(v14);
}
v26 = -1;
v20 = 0;
v21 = 15;
LOBYTE(Memory) = 0;
if ( v24 >= 0x10 )
{
v15 = Dst;
if ( v24 + 1 >= 0x1000 )
{
v15 = (_BYTE *)*((_DWORD *)Dst - 1);
if ( (unsigned int)((_BYTE *)Dst - v15 - 4) > 0x1F )
invalid_parameter_noinfo_noreturn(v15, v24 + 36);
}
frees(v15);
}
v16 = "Have fun!";
if ( v13 )
v16 = "A forged ticket!!";
v17 = sub_402870(std::cout, v16);
std::basic_ostream<char,std::char_traits<char>>::operator<<(v17, sub_402AC0);
system("pause");
return 0;
}
查看sub_402320函数的代码发现
void __thiscall sub_402320(_DWORD *this)
{
int v1; // eax
__int16 v2; // bx
const char *v3; // esi
signed int i; // edi
int v5; // eax
v1 = this;
v2 = *(_WORD *)((char *)this + v1 + 6);
v3 = (char *)this + v1 + 248;
for ( i = 0; i < v2; ++i ) // 判断区段
{
v5 = strcmp(v3, ".SCTF");
if ( v5 )
v5 = -(v5 < 0) | 1;
if ( !v5 )
{
DebugBreak();
return;
}
v3 += 40;
}
}
读取区段,判断区段是否是.SCTF区段。
如果是,就会跳到loc_4023EF并在里边调用函数解密区段。
.text:004023EF loc_4023EF: ; DATA XREF: .rdata:stru_407B58↓o
.text:004023EF mov esp,
.text:004023F2 lea eax,
.text:004023F5 push eax ; pbDebuggerPresent
.text:004023F6 call ds:GetCurrentProcess
.text:004023FC push eax ; hProcess
.text:004023FD call ds:CheckRemoteDebuggerPresent
.text:00402403 call ds:IsDebuggerPresent
.text:00402409 test eax, eax
.text:0040240B jnz short loc_4023B9
.text:0040240D cmp , eax
.text:00402410 jnz short loc_4023B9
.text:00402412 mov eax,
.text:00402415 mov edx,
.text:00402418 mov ecx,
.text:0040241B add ecx,
.text:0040241E mov esi,
.text:00402421 lea edi,
.text:00402424
.text:00402424 loc_402424: ; CODE XREF: sub_402320+109↓j
.text:00402424 mov al, ; sycloversyclover
.text:00402426 inc esi
.text:00402427 test al, al
.text:00402429 jnz short loc_402424 ; sycloversyclover
.text:0040242B sub esi, edi
.text:0040242D push esi
.text:0040242E push ecx
.text:0040242F call sub_402450
.text:00402434 add esp, 8
.text:00402437 jmp short loc_4023B9
.text:00402439 ; ---------------------------------------------------------------------------
.text:00402439
.text:00402439 loc_402439: ; CODE XREF: sub_402320+8A↑j
.text:00402439 add esi, 28h
.text:0040243C inc edi
.text:0040243D jmp loc_402372
.text:0040243D sub_402320 endp
在sub_4024A0函数中,会进入.SCTF区段。
主要是解密>pvfqYc,4tTc2UxRmlJ,sB{Fh4Ck2:CFOb4ErhtIcoLo
解密成nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=
sub_4020D0函数其实就是AES加密。
CBC模式,密码为sycloversyclover,偏移量为sctfsctfsctfsctf。
最终得到
Bybare
一道游戏题,总共有三关。
第一关,
.text:00005593B1D94798 main: ; DATA XREF: start+1D↑o
.text:00005593B1D94798 ; __unwind {
.text:00005593B1D94798 push rbp
.text:00005593B1D94799 mov rbp, rsp
.text:00005593B1D9479C sub rsp, 160h
.text:00005593B1D947A3 mov rax, fs:28h
.text:00005593B1D947AC mov , rax
.text:00005593B1D947B0 xor eax, eax
.text:00005593B1D947B2 mov dword ptr , 0
.text:00005593B1D947BC mov qword ptr , 0
.text:00005593B1D947C7 mov qword ptr , 0
.text:00005593B1D947D2 mov qword ptr , 0
.text:00005593B1D947DD mov byte ptr , 0
.text:00005593B1D947E4 mov qword ptr , 0
.text:00005593B1D947EF mov qword ptr , 0
.text:00005593B1D947FA mov qword ptr , 0
.text:00005593B1D94805 mov byte ptr , 0
.text:00005593B1D9480C mov qword ptr , 0
.text:00005593B1D94817 mov qword ptr , 0
.text:00005593B1D94822 mov qword ptr , 0
.text:00005593B1D9482D mov qword ptr , 0
.text:00005593B1D94838 mov qword ptr , 0
.text:00005593B1D94843 mov qword ptr , 0
.text:00005593B1D9484E mov word ptr , 0
.text:00005593B1D94857 mov rax, '********'
.text:00005593B1D94861 mov rdx, '*.******'
.text:00005593B1D9486B mov , rax
.text:00005593B1D94872 mov , rdx
.text:00005593B1D94879 mov rax, '.s**.***'
.text:00005593B1D94883 mov rdx, '****..*.'
.text:00005593B1D9488D mov , rax
.text:00005593B1D94891 mov , rdx
.text:00005593B1D94895 mov rax, '.****.**'
.text:00005593B1D9489F mov rdx, '********'
.text:00005593B1D948A9 mov , rax
.text:00005593B1D948AD mov , rdx
.text:00005593B1D948B1 mov rax, '***..***'
.text:00005593B1D948BB mov rdx, '*#..**..'
.text:00005593B1D948C5 mov , rax
.text:00005593B1D948C9 mov , rdx
.text:00005593B1D948CD mov rax, '*..***..'
.text:00005593B1D948D7 mov rdx, '*****.**'
.text:00005593B1D948E1 mov , rax
.text:00005593B1D948E5 mov , rdx
.text:00005593B1D948E9 mov rax, '********'
.text:00005593B1D948F3 mov rdx, '.*******'
.text:00005593B1D948FD mov , rax
.text:00005593B1D94901 mov , rdx
.text:00005593B1D94905 mov rax, '****..**'
.text:00005593B1D9490F mov rdx, '.**..***'
.text:00005593B1D94919 mov , rax
.text:00005593B1D9491D mov , rdx
.text:00005593B1D94921 mov rax, '*.*..*..'
.text:00005593B1D9492B mov , rax
.text:00005593B1D9492F mov dword ptr , '.**.'
.text:00005593B1D94936 mov word ptr , 2Ah ; '*'
.text:00005593B1D9493C mov qword ptr , 0
.text:00005593B1D94947 mov qword ptr , 0
.text:00005593B1D94952 mov dword ptr , 0
.text:00005593B1D9495C lea rax,
.text:00005593B1D94963 add rax, 16h
.text:00005593B1D94967 mov , rax
.text:00005593B1D9496E mov rax, '019_ftcs' ; sctf_019
.text:00005593B1D94978 mov , rax
.text:00005593B1D9497F mov word ptr , 32h ; '2' ; sctf_2019
.text:00005593B1D94988 xor rax, rax
.text:00005593B1D9498B jb short loc_5593B1D94990
.text:00005593B1D9498D jnb short loc_5593B1D94990
.text:00005593B1D9498D ; ---------------------------------------------------------------------------
.text:00005593B1D9498F db 0E1h
.text:00005593B1D94990 ; ---------------------------------------------------------------------------
.text:00005593B1D94990
.text:00005593B1D94990 loc_5593B1D94990: ; CODE XREF: .text:00005593B1D9498B↑j
.text:00005593B1D94990 ; .text:00005593B1D9498D↑j
.text:00005593B1D94990 lea rdi, aPlzTellMeTheSh ; "plz tell me the shortest password1:"
.text:00005593B1D94997 call _puts
.text:00005593B1D9499C lea rax,
.text:00005593B1D949A3 mov rsi, rax
.text:00005593B1D949A6 lea rdi, aS ; "%s"
.text:00005593B1D949AD mov eax, 0
.text:00005593B1D949B2 call _scanf
.text:00005593B1D949B7 mov dword ptr , 1
.text:00005593B1D949C1
.text:00005593B1D949C1 loc_5593B1D949C1: ; CODE XREF: .text:00005593B1D94A9F↓j
.text:00005593B1D949C1 cmp dword ptr , 0
.text:00005593B1D949C8 jz loc_5593B1D94AB1
.text:00005593B1D949CE mov eax,
.text:00005593B1D949D4 cdqe
.text:00005593B1D949D6
.text:00005593B1D949D6 loc_5593B1D949D6:
.text:00005593B1D949D6 lea rdx,
.text:00005593B1D949DD add rax, rdx
.text:00005593B1D949E0 movzx eax, byte ptr
.text:00005593B1D949E3 mov , al
.text:00005593B1D949E9 cmp byte ptr , 77h ; 'w'
.text:00005593B1D949F0 jnz short loc_5593B1D949FC
.text:00005593B1D949F2 sub qword ptr , 5
.text:00005593B1D949FA jmp short loc_5593B1D94A66
.text:00005593B1D949FC ; ---------------------------------------------------------------------------
.text:00005593B1D949FC
.text:00005593B1D949FC loc_5593B1D949FC: ; CODE XREF: .text:00005593B1D949F0↑j
.text:00005593B1D949FC cmp byte ptr , 73h ; 's'
.text:00005593B1D94A03 jnz short loc_5593B1D94A0F
.text:00005593B1D94A05 add qword ptr , 5
.text:00005593B1D94A0D jmp short loc_5593B1D94A66
.text:00005593B1D94A0F ; ---------------------------------------------------------------------------
.text:00005593B1D94A0F
.text:00005593B1D94A0F loc_5593B1D94A0F: ; CODE XREF: .text:00005593B1D94A03↑j
.text:00005593B1D94A0F cmp byte ptr , 64h ; 'd'
.text:00005593B1D94A16 jnz short loc_5593B1D94A22
.text:00005593B1D94A18 add qword ptr , 1
.text:00005593B1D94A20 jmp short loc_5593B1D94A66
.text:00005593B1D94A22 ; ---------------------------------------------------------------------------
.text:00005593B1D94A22
.text:00005593B1D94A22 loc_5593B1D94A22: ; CODE XREF: .text:00005593B1D94A16↑j
.text:00005593B1D94A22 cmp byte ptr , 61h ; 'a'
.text:00005593B1D94A29 jnz short loc_5593B1D94A35
.text:00005593B1D94A2B sub qword ptr , 1
.text:00005593B1D94A33 jmp short loc_5593B1D94A66
.text:00005593B1D94A35 ; ---------------------------------------------------------------------------
.text:00005593B1D94A35
.text:00005593B1D94A35 loc_5593B1D94A35: ; CODE XREF: .text:00005593B1D94A29↑j
.text:00005593B1D94A35 cmp byte ptr , 78h ; 'x'
.text:00005593B1D94A3C jnz short loc_5593B1D94A48
.text:00005593B1D94A3E add qword ptr , 19h
.text:00005593B1D94A46 jmp short loc_5593B1D94A66
.text:00005593B1D94A48 ; ---------------------------------------------------------------------------
.text:00005593B1D94A48
.text:00005593B1D94A48 loc_5593B1D94A48: ; CODE XREF: .text:00005593B1D94A3C↑j
.text:00005593B1D94A48 cmp byte ptr , 79h ; 'y'
.text:00005593B1D94A4F jnz short loc_5593B1D94A5B
.text:00005593B1D94A51 sub qword ptr , 19h
.text:00005593B1D94A59 jmp short loc_5593B1D94A66
.text:00005593B1D94A5B ; ---------------------------------------------------------------------------
.text:00005593B1D94A5B
.text:00005593B1D94A5B loc_5593B1D94A5B: ; CODE XREF: .text:00005593B1D94A4F↑j
.text:00005593B1D94A5B mov dword ptr , 0
.text:00005593B1D94A65 nop
.text:00005593B1D94A66
.text:00005593B1D94A66 loc_5593B1D94A66: ; CODE XREF: .text:00005593B1D949FA↑j
.text:00005593B1D94A66 ; .text:00005593B1D94A0D↑j ...
.text:00005593B1D94A66 add dword ptr , 1
.text:00005593B1D94A6D mov rax,
.text:00005593B1D94A74 movzx eax, byte ptr
.text:00005593B1D94A77 cmp al, 2Eh ; '.'
.text:00005593B1D94A79 jz short loc_5593B1D94A93
.text:00005593B1D94A7B mov rax,
.text:00005593B1D94A82 movzx eax, byte ptr
.text:00005593B1D94A85 cmp al, 23h ; '#'
.text:00005593B1D94A87 jz short loc_5593B1D94A93
.text:00005593B1D94A89 mov dword ptr , 0
.text:00005593B1D94A93
.text:00005593B1D94A93 loc_5593B1D94A93: ; CODE XREF: .text:00005593B1D94A79↑j
.text:00005593B1D94A93 ; .text:00005593B1D94A87↑j
.text:00005593B1D94A93 mov rax,
.text:00005593B1D94A9A movzx eax, byte ptr
.text:00005593B1D94A9D cmp al, 23h ; '#'
.text:00005593B1D94A9F jnz loc_5593B1D949C1
.text:00005593B1D94AA5 lea rdi, aGoodYouFindThe ; "good!you find the right way!\nBut there"...
.text:00005593B1D94AAC call _puts
.text:00005593B1D94AB1
.text:00005593B1D94AB1 loc_5593B1D94AB1: ; CODE XREF: .text:00005593B1D949C8↑j
.text:00005593B1D94AB1 cmp dword ptr , 0
.text:00005593B1D94AB8 jnz short loc_5593B1D94AD5
.text:00005593B1D94ABA lea rdi, aSorryIsTNotARi ; "sorry,is't not a right way..."
.text:00005593B1D94AC1 mov eax, 0
.text:00005593B1D94AC6 call _printf
.text:00005593B1D94ACB mov eax, 0
.text:00005593B1D94AD0 jmp loc_5593B1D94C0C
先赋值迷宫,总共六个控制键,好像是三维的,但是可以化成一维。
w/s分别为后退/前进五格,a/d分别为后退/前进一格,y/x分别为后退/前进25格。
把迷宫换成一维,最终要使s和#相遇。
**************.****.**s..*..******.****.***********..***..**..#*..***..***.*****
得到sxss
第二关。
输入字符进入进入函数,最终和sctf_9102对比。
汇编看起来比较麻烦,不能f5的原因是中间多了一个0XE4字节,可以手动nop掉。
.text:0000000000000E11 jnb short loc_E14
.text:0000000000000E11 ; ---------------------------------------------------------------------------
.text:0000000000000E13 db 0E4h
.text:0000000000000E14 ; ---------------------------------------------------------------------------
.text:0000000000000E14
.text:0000000000000E14 loc_E14: ; CODE XREF: .text:0000000000000E0F↑j
.text:0000000000000E14 ; .text:0000000000000E11↑j
.text:0000000000000E14 mov dword ptr , 0
.text:0000000000000E1E
.text:0000000000000E1E loc_E1E: ; CODE XREF: .text:0000000000000F4B↓j
.text:0000000000000E1E cmp dword ptr , 0
nop之后
unsigned __int64 __fastcall sub_C22(const char *a1, __int64 a2)
{
bool v2; // al
int v3; // eax
int v4; // eax
int v5; // eax
int v7; //
signed int v8; //
int v9; //
int v10; //
int v11; //
int v12; //
int v13; //
char *v14; //
int v15; //
unsigned __int64 v16; //
v16 = __readfsqword(0x28u);
qmemcpy(v15, &off_1740, 0x200uLL);
v8 = 3;
v7 = 0;
v10 = 0;
v11 = 0;
v12 = strlen(a1);
v14 = (char *)a1;
while ( 1 )
{
v13 = 0;
if ( v10 < v12 )
break;
LABEL_13:
if ( v10 >= v12 )
goto LABEL_14;
}
do
{
if ( a1 != 25 )
break;
++v10;
++v13;
}
while ( v10 < v12 );
if ( v10 != v12 )
{
if ( v12 - v10 > 1 )
{
v2 = v10 == 19 && a1 == 16;
a1;
}
++v10;
goto LABEL_13;
}
LABEL_14:
v9 = 0;
while ( v12 > 0 )
{
v8 -= v15[*v14] == 64;
v7 = v15[*v14] & 0x3F | (v7 << 6);
if ( ++v9 == 4 )
{
v9 = 0;
if ( v8 )
{
v3 = v11++;
*(_BYTE *)(v3 + a2) = BYTE2(v7);
}
if ( v8 > 1 )
{
v4 = v11++;
*(_BYTE *)(v4 + a2) = BYTE1(v7);
}
if ( v8 > 2 )
{
v5 = v11++;
*(_BYTE *)(v5 + a2) = v7;
}
}
++v14;
--v12;
}
return __readfsqword(0x28u) ^ v16;
}
其实这代码的原理就是,输入字符分成四个一组,每次取8位二进制索引字符,取字符低6位,一组可以得到4个6位二进制,最终一组得到3个字符。
可以逆推得到password2:c2N0Zl85MTAy
第三关。
signed __int64 __fastcall sub_5593B1D94FFA(char *a1)
{
int v1; // ST24_4
int v2; // ST28_4
int v3; // ST2C_4
signed int v5; //
signed int i; //
int cout; //
int v8; //
int v9; //
int v10; //
unsigned int v11; //
unsigned __int64 v12; //
v12 = __readfsqword(0x28u);
v8 = 0xBE;
v8 = '\x04';
v8 = '\x06';
v8 = 0x80;
v8 = 0xC5;
v8 = 0xAF;
v8 = 0x76;
v8 = 0x47;
v8 = 0x9F;
v8 = 0xCC;
v8 = 0x40;
v8 = 0x1F;
v8 = 0xD8;
v8 = 0xBF;
v8 = 0x92;
v8 = 0xEF;
v1 = (a1 << 8) | (a1 << 16) | (a1 << 24) | a1;
v2 = (a1 << 8) | (a1 << 16) | (a1 << 24) | a1;
v3 = (a1 << 8) | (a1 << 16) | (a1 << 24) | a1;// 16位
cout = 0;
v5 = 4;
v10 = byteswap_ulong((a1 << 8) | (a1 << 16) | (*a1 << 24) | (unsigned int)a1);// 颠倒过来排列
v10 = byteswap_ulong(v1);
v10 = byteswap_ulong(v2);
v10 = byteswap_ulong(v3);
do
{
v10 = sub_5593B1D9543B(v10, v10, v10, v10);
++cout;
++v5;
}
while ( v5 <= 29 );
v9 = (unsigned int)v10 >> 24;
v9 = BYTE2(v10);
v9 = BYTE1(v10);
v9 = LOBYTE(v10);
v9 = (unsigned int)v10 >> 24;
v9 = BYTE2(v10);
v9 = BYTE1(v10);
v9 = LOBYTE(v10);
v9 = (unsigned int)v10 >> 24;
v9 = BYTE2(v10);
v9 = BYTE1(v10);
v9 = LOBYTE(v10);
v9 = v11 >> 24;
v9 = BYTE2(v11);
v9 = BYTE1(v11);
v9 = (unsigned __int8)v11;
for ( i = 0; i <= 15; ++i )
{
if ( v9 != v8 )
return 0xFFFFFFFFLL;
}
return 1LL;
}
__int64 __fastcall sub_5593B1D9543B(int a1, int a2, int a3, unsigned int a4)
{
return a1 ^ (unsigned int)sub_5593B1D95464(a2 ^ a3 ^ a4);
}
__int64 __fastcall sub_5593B1D95464(unsigned int a1)
{
int v1; // ST18_4
int v3; //
unsigned __int64 v4; //
v4 = __readfsqword(0x28u);
qmemcpy(v3, &byte_5593B1D95940, 1152uLL);
v1 = (v3 << 16) | v3[(unsigned __int8)a1] | (v3 << 8) | (v3 << 24);
return __ROL4__(v1, 12) ^ (unsigned int)(__ROL4__(v1, 8) ^ __ROR4__(v1, 2)) ^ __ROR4__(v1, 6);
}
输入字符,长度为16,分为四位一组,组成4个int元素,再大小端颠倒。然后第2,3,4元素异或进入函数索引字符再循环异或再跟第一个元素异或得到第五个元素,再用2,3,4,5重复相同步骤得到第六个元素,以此类推。
循环26次,取最高四个元素跟程序的值对比,可以写脚本逆推。
i=
asc =
def xors(xor_mix):
temp1 = (xor_mix >> 24)&0xff
temp2 = (xor_mix >> 16)&0xff
temp3 = (xor_mix >> 8)&0xff
temp = (xor_mix)&0xff
temp_q = asc | (asc<<24)|(asc<<16)|(asc<<8)
print ("%x"%(temp_q))
temp_i = ((temp_q <<12|temp_q>>20)&0xffffffff) ^ ((temp_q <<8|temp_q>>24)&0xffffffff) ^ ((temp_q>>2|temp_q<<30)&0xffffffff)^((temp_q>>6|temp_q<<26)&0xffffffff)
return temp_i
print ("%x"%(xors(0x6011F432)))
print (len(asc))
for q in range(26):
i.append(i^xors(i^i^i))
print (i)
print ("%x"%(i[-1]))
print ("%x"%(i[-2]))
print ("%x"%(i[-3]))
print ("%x"%(i[-4]))
# fl4g_is_s0_ug1y!
得到fl4g_is_s0_ug1y!
music
app打开需要联网,不懂为啥。
查看代码
package com.example.music;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class q
{
private h h;
private Context mycontext;
public q(Context paramContext)
{
this.mycontext = paramContext;
}
public String get()
{
String str1 = null;
this.h = new h(this.mycontext, "sctf.db", null, 1);
Cursor localCursor = this.h.getWritableDatabase().query("SYC", null, null, null, null, null, null);
if (localCursor.moveToFirst()) {
do
{
str1 = localCursor.getString(localCursor.getColumnIndex("S1"));
String str2 = localCursor.getString(localCursor.getColumnIndex("S2"));
StringBuilder localStringBuilder = new StringBuilder();
localStringBuilder.append(str1);
localStringBuilder.append(str2);
str1 = localStringBuilder.toString();
} while (localCursor.moveToNext());
}
localCursor.close();
return str1;
}
}
发现程序里边有.db文件,用SQLiteSpy打开。
得到hellosctf
package com.example.music;
import java.security.MessageDigest;
public class a
{
public String a(String paramString)
{
return b(paramString);
}
public String b(String paramString)
{
new p();
if (paramString != null) {
try
{
paramString = p.a(MessageDigest.getInstance("MD5").digest(paramString.getBytes()));
return paramString;
}
catch (Exception paramString)
{
paramString.printStackTrace();
}
}
return null;
}
}
package com.example.music;
public class p
{
public static String a(byte[] paramArrayOfByte)
{
StringBuffer localStringBuffer = new StringBuffer();
int i = 0;
while (i < paramArrayOfByte.length)
{
String str = Integer.toHexString(paramArrayOfByte & 0xFF);
Object localObject = str;
if (str.length() == 1)
{
localObject = new StringBuilder();
((StringBuilder)localObject).append('0');
((StringBuilder)localObject).append(str);
localObject = ((StringBuilder)localObject).toString();
}
localStringBuffer.append(((String)localObject).toUpperCase());
i += 1;
}
return localStringBuffer.toString();
}
}
字母变大写,得到E7E64BF658BAB14A25C9D67A054CEBE5
然后和输入字符进入加密。
package com.example.music;
public class c
{
private static int m = 256;
public String a(String paramString1, String paramString2)
{
int i = m;
int[] arrayOfInt = new int;
byte[] arrayOfByte = new byte;
i = 0;
while (i < m)
{
arrayOfInt = i;
arrayOfByte = ((byte)paramString2.charAt(i % paramString2.length()));
i += 1;
}
i = 0;
int j = 0;
for (;;)
{
k = m;
if (i >= k - 1) {
break;
}
j = (arrayOfInt + j + arrayOfByte) % k;
k = arrayOfInt;
arrayOfInt = arrayOfInt;
arrayOfInt = k;
i += 1;
}
paramString2 = paramString1.toCharArray();
paramString1 = new char;
int k = 0;
j = 0;
i = 0;
while (i < paramString2.length)
{
int n = m;
k = (k + 1) % n;
j = (arrayOfInt + j) % n;
int i1 = arrayOfInt;
arrayOfInt = arrayOfInt;
arrayOfInt = i1;
i1 = arrayOfInt;
int i2 = arrayOfInt;
paramString1 = ((char)(paramString2 - k ^ (char)arrayOfInt[((i1 + i2 % n) % n)]));
i += 1;
}
new p();
return p.a(new String(paramString1).getBytes());
}
}
看起来是变种RC4
最终对比
public boolean g(String paramString)
{
return paramString.equals(s.this.getApplicationContext().getResources().getString(2131492904));
}
没动态调试环境,一直调试不了,后来发现应该是储存在Strings.xml文件里边。
<string name="cipher">C28BC39DC3A6C283C2B3C39DC293C289C2B8C3BAC29EC3A0C3A7C29A1654C3AF28C3A1C2B1215B53</string>
<string name="local">/data/data/com.example.music/databases/</string>
<string name="no">wrong!</string>
<string name="search_menu_title">Search</string>
<string name="song">http://www.ytmp3.cn/down/44093.mp3</string>
得到密文,看到一个网址,应该是需要联网的原因,程序开始需要听一段音乐,音乐应该就是这个网址里边的。
密文是经过大写变换的,变成小写可以得到c28bc39dc3a6c283c2b3c39dc293c289c2b8c3bac29ec3a0c3a7c29a1654c3af28c3a1c2b1215b53
但是即使这样,用python写脚本一直写不通.
import base64
flag = "c28bc39dc3a6c283c2b3c39dc293c289c2b8c3bac29ec3a0c3a7c29a1654c3af28c3a1c2b1215b53"
flagh = []
for q in range(0,len(flag),2):
flagh.append(int(flag,16))
print flagh
S = []
T = []
key = "E7E64BF658BAB14A25C9D67A054CEBE5"
# C28BC39DC3A6C283C2B3C39DC293C289C2B8C3BAC29EC3A0C3A7C29A1654C3AF28C3A1C2B1215B53
# c28bc39dc3a6c283c2b3c39dc293c289c2b8c3bac29ec3a0c3a7c29a1654c3af28c3a1c2b1215b53
for i in range(256):
S.append(i)
T.append(key)
#print S
#print T
j = 0
for i in range(256):
j = (j+S+ord(T))%256
S,S=S,S
i = 0
j = 0
k = []
# for r in range(len(flag)):
# i = (i+1)%256
# j = (j+S)%256
# S,S = S,S
# t = (S+S)%256
# k.append(S)
#
flags = []
for r in range(len(flagh)):
i = (i+1)%256
j = (j+S)%256
S,S = S,S
t = (S+S)%256
k.append(S)
flags.append((flagh ^ S[(S + S % 256) % 256]) + i)
print flags
后来发现先知社区有大佬写wp了。
引用他们的脚本
https://xz.aliyun.com/t/5478#toc-21
public class Notepad
{
public static void main(String[] args)
{
byte[] enctob = new byte[]{-62, -117, -61, -99, -61, -90, -62, -125, -62, -77, -61, -99, -62, -109, -62, -119, -62, -72, -61, -70, -62, -98, -61, -96, -61, -89, -62, -102, 22, 84, -61, -81, 40, -61, -95, -62, -79, 33, 91, 83};
String bs = new String(enctob);
char[] flagenc = bs.toCharArray();
char[] out = new char;
int[] S = new int;
byte[] wtf = new byte;
int i,j,k;
String key = "E7E64BF658BAB14A25C9D67A054CEBE5";
for (i = 0; i < 256; i++ )
{
S = i;
wtf = (byte)(key.charAt(i % 32));
}
i = 0;
j = 0;
for(i = 0,j = 0;i < 256; i++ )
{
j = (S + j + wtf) % 256;
k = S;
S = S;
S = k;
}
for (i = 0,j = 0,k = 0; i < bs.length(); i++ )
{
k = (k + 1) % 256;
j = (S + j) % 256;
int temp = S;
S = S;
S = temp;
out = (char)((flagenc ^ S[(S + S % 256) % 256]) + k);
System.out.println(out);
}
}
}
得到flag
他们中出现了两句
String bs = new String(enctob);
char[] flagenc = bs.toCharArray();
可能是编码问题,这个问题有待解决
编码问题是因为一个字符getByte是两个 大佬写的博客太好了。。。。。 想前排请问一下大佬 第一个题的脚本有没有 别的方法(感觉这个有点麻烦鸭) 瑟瑟发抖小菜虾 发表于 2019-6-24 21:25
大佬写的博客太好了。。。。。 想前排请问一下大佬 第一个题的脚本有没有 别的方法(感觉这个有点麻烦鸭)
应该有吧,只不过我对安卓平台接触不多不知道。 https://i.imgur.com/3bFW2nl.jpg 本帖最后由 Hotspur 于 2019-6-26 17:30 编辑
膜拜大佬,当时babyre那题卡在最后一步半天没做出来。。。
第二步其实是个base64解密。。不过要多输入一个‘=’。。当时把最后一位是’=‘推出来后直接想到base,一解密还真成了。 Hotspur 发表于 2019-6-26 17:22
膜拜大佬,当时babyre那题卡在最后一步半天没做出来。。。
第二步其实是个base64解密。。不过要多输入一个 ...
嗯,就是base64解密,还原之后才反映过来
页:
[1]