Cat Solution

[Rev] squ1rrel CTF 2025 droid Write-Up 본문

CTF/Reversing

[Rev] squ1rrel CTF 2025 droid Write-Up

Casol 2025. 4. 7. 12:12

문제 설명

this is not the android you're looking for

 

문제 파일

droid.apk

 


 

 

 

Correct! 가 뜨는 입력값을 찾으면 될 것 같다.

 

 

MainActivityKt.smali 내부에 Correct! / Incorrect! 문자열이 존재했고, Correct! 로 이동하는 조건문을 살펴봤다.

 

    invoke-static {p1}, Lla/nisa/nisalashouse2/MainActivityKt;->TextBoxWithButton$lambda$1(Landroidx/compose/runtime/MutableState;)Ljava/lang/String;

    move-result-object v0

    invoke-static {v0}, Lla/nisa/nisalashouse2/MainActivityKt;->check(Ljava/lang/String;)Z

    move-result v0

 

사용자가 입력한 텍스트 (v0)을 check() 함수로 보내 맞는지 검사하고

 

if-eqz v0, :cond_0

    const-string v0, "Correct!"

    goto :goto_0

    :cond_0
    const-string v0, "Incorrect!"

    :goto_0
    invoke-static {p2, v0}, Lla/nisa/nisalashouse2/MainActivityKt;->TextBoxWithButton$lambda$5(Landroidx/compose/runtime/MutableState;Ljava/lang/String;)V

 

check() 함수의 리턴값이 true 면 Correct! 를 표시한다.

check() 의 로직을 분석하면 정답을 얻을 수 있을 것 같다.

 

.method public static final check(Ljava/lang/String;)Z
    .locals 12
    .param p0, "text"    # Ljava/lang/String;

    const-string v0, "text"

    invoke-static {p0, v0}, Lkotlin/jvm/internal/Intrinsics;->checkNotNullParameter(Ljava/lang/Object;Ljava/lang/String;)V

    .line 49
    invoke-virtual {p0}, Ljava/lang/String;->length()I

    move-result v0

    sget-object v1, Lla/nisa/nisalashouse2/MainActivityKt;->expected:[I

    array-length v1, v1

    if-eq v0, v1, :cond_0

    .line 50
    const/4 v0, 0x0

    return v0

    .line 52
    :cond_0
    sget-object v0, Lla/nisa/nisalashouse2/MainActivityKt;->expected:[I

    array-length v0, v0

    new-array v0, v0, [I

    .line 53
    .local v0, "result":[I
    const/4 v1, 0x0

    .local v1, "i":I
    sget-object v2, Lla/nisa/nisalashouse2/MainActivityKt;->expected:[I

    array-length v2, v2

    :goto_0
    if-ge v1, v2, :cond_1

    .line 55
    invoke-virtual {p0, v1}, Ljava/lang/String;->charAt(I)C

    move-result v3

    sget-object v4, Lla/nisa/nisalashouse2/MainActivityKt;->key:[I

    aget v4, v4, v1

    xor-int/2addr v3, v4

    aput v3, v0, v1

    .line 53
    add-int/lit8 v1, v1, 0x1

    goto :goto_0

    .line 58
    .end local v1    # "i":I
    :cond_1
    const/16 v8, 0x3f

    const/4 v9, 0x0

    const/4 v2, 0x0

    const/4 v3, 0x0

    const/4 v4, 0x0

    const/4 v5, 0x0

    const/4 v6, 0x0

    const/4 v7, 0x0

    move-object v1, v0

    invoke-static/range {v1 .. v9}, Lkotlin/collections/ArraysKt;->joinToString$default([ILjava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;

    move-result-object v1

    sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;

    invoke-virtual {v2, v1}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V

    .line 59
    sget-object v3, Lla/nisa/nisalashouse2/MainActivityKt;->expected:[I

    const/16 v10, 0x3f

    const/4 v11, 0x0

    const/4 v5, 0x0

    const/4 v7, 0x0

    const/4 v8, 0x0

    invoke-static/range {v3 .. v11}, Lkotlin/collections/ArraysKt;->joinToString$default([ILjava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;

    move-result-object v1

    sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;

    invoke-virtual {v2, v1}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V

    .line 60
    sget-object v1, Lla/nisa/nisalashouse2/MainActivityKt;->expected:[I

    invoke-static {v0, v1}, Ljava/util/Arrays;->equals([I[I)Z

    move-result v1

    return v1
.end method

 

check() 함수 로직

입력 문자열의 길이와 expected 배열의 길이가 다르면 false 반환

입력 문자열의 각 문자와 key 배열을 XOR 연산하여 결과를 result 배열에 저장

result 배열이 expected 배열과 같은지 확인

 

따라서 입력값[i]^key[i] == result[i] == expected[i] 여야하므로

key 배열과 expected 배열을 XOR 연산 해주면 올바른 입력값을 구할 수 있겠다.

 

key, expected 배열이 정의된 부분

 

연산 결과 flag를 구할 수 있었다.

 


 

flag

fsqu1rrel{k0tl1n_is_c001_n1s4l4}