picoctf 2019

Reverse

VaultDoor系列題目

給你一段java的code

然後推Flag

Vault-door-training

簡單的驗證

public boolean checkPassword(String password) {
        return password.equals("w4rm1ng_Up_w1tH_jAv4_3b500738c12");
    }

Vault-door-1

字元檢查

public boolean checkPassword(String password) {
        return password.length() == 32 &&
               password.charAt(0)  == 'd' &&
               password.charAt(29) == 'f' &&
               password.charAt(4)  == 'r' &&
               password.charAt(2)  == '5' &&
               password.charAt(23) == 'r' &&
               password.charAt(3)  == 'c' &&
               password.charAt(17) == '4' &&
               password.charAt(1)  == '3' &&
               password.charAt(7)  == 'b' &&
               password.charAt(10) == '_' &&
               password.charAt(5)  == '4' &&
               /* ....*/
}

Vault-door-3

不太單純??

for (i=0; i<8; i++) {
            buffer[i] = password.charAt(i);
        }
for (; i<16; i++) {
            buffer[i] = password.charAt(23-i);
        }
for (; i<32; i+=2) {
            buffer[i] = password.charAt(46-i);
        }
for (i=31; i>=17; i-=2) {
            buffer[i] = password.charAt(i);
        }
String s = new String(buffer);
        return s.equals("jU5t_a_sna_3lpm16g84c_u_4_m0r846");

嘗試畫表

0 1 2 3 4 5 6 7
j U 5 t _ a _ s

na_3lpm16g84c_u_4_m0r846

for (i=0; i<8; i++) {
            buffer[i] = password.charAt(i);
        }

jU5t_a_s

嘗試畫表

8 9 10 11 12 13 14 15
1 m p l 3 _ a n
for (; i<16; i++) {
            buffer[i] = password.charAt(23-i);
        }

6g84c_u_4_m0r846

na_3lpm1

jU5t_a_s

嘗試畫表

17 19 21 23 25 27 29 31
g 4 _ _ _ 0 8 6

6g84c_u_4_m0r846

na_3lpm1

jU5t_a_s

for (i=31; i>=17; i-=2) {
            buffer[i] = password.charAt(i);
        }

嘗試畫表

16
(46-30)
18
(46-28)
20
(46-26)
22
(46-24)
24
(46-22)
26
​(46-20)
28
(46-18)
30
(46-16)
4 r m 4 u c 8 6
for (; i<32; i+=2) {
            buffer[i] = password.charAt(46-i);
        }

6g84c_u_4_m0r846

na_3lpm1

jU5t_a_s

Merge

0 1 2 3 4 5 6 7
j U 5 t _ a _ s
8 9 10 11 12 13 14 15
1 m p l 3 _ a n
16 18 20 22 24 26 28 30
4 r m 4 u c 8 6
17 19 21 23 25 27 29 31
g 4 _ _ _ 0 8 6

累?

其實你將結果倒著做就可以了

char s[32]="jU5t_a_sna_3lpm16g84c_u_4_m0r846";
    char buffer[32];
    int i;
    
    for (i=0; i<8; i++) {
        buffer[i] = s[i];
    }
    for (; i<16; i++) {
        buffer[i] = s[23-i];
    }
    for (; i<32; i+=2) {
        buffer[i] =s[46-i];
    }
    for (i=31; i>=17; i-=2) {
        buffer[i] = s[i];
    }
    
    for(i = 0; i < 32; i++)
        printf("%c",buffer[i]);
 public boolean checkPassword(String password) {
        byte[] passBytes = password.getBytes();
        byte[] myBytes = {
            106 , 85  , 53  , 116 , 95  , 52  , 95  , 98  ,
            0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f,
            0142, 0131, 0164, 063 , 0163, 0137, 063 , 0141,
            '7' , '2' , '4' , 'c' , '8' , 'f' , '9' , '2' ,
        };

Vault-door-4

一切都是ASCII

直接轉型

 int myBytes[32] = {
            106 , 85  , 53  , 116 , 95  , 52  , 95  , 98  ,
            0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f,
            0142, 0131, 0164, 063 , 0163, 0137, 063 , 0141,
            '7' , '2' , '4' , 'c' , '8' , 'f' , '9' , '2' ,
        };
        
    for(int i = 0; i < 32; i++)
        printf("%c",myBytes[i]);

Vault-door-5

public boolean checkPassword(String password) {
        String urlEncoded = urlEncode(password.getBytes());
        String base64Encoded = base64Encode(urlEncoded.getBytes());
        String expected = "JTYzJTMwJTZlJTc2JTMzJTcyJTc0JTMxJTZlJTY3JTVm"
                        + "JTY2JTcyJTMwJTZkJTVmJTYyJTYxJTM1JTY1JTVmJTM2"
                        + "JTM0JTVmJTMxJTMxJTM3JTM3JTY2JTM3JTM4JTMz";
        return base64Encoded.equals(expected);
    }

Vault-door-5

base64_decode

URL_decode

Vault-door-6

byte[] myBytes = {
            0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d,
            0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa ,
            0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27,
            0xa , 0x63, 0x65, 0x64, 0x67, 0x37, 0x6d, 0x62,
        };
        for (int i=0; i<32; i++) {
            if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) {
                return false;
            }
        }

Vault-door-6

if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) {
                return false;
            }

不讓他return false

passBytes[i] ^ 0x55 =  myBytes[i]

這兩個要一樣

Vault-door-6

XOR 特性

passBytes[i] ^ 0x55 =  myBytes[i]

A  B = C

A  C = B

Proof:

A  B = C

A A  B = A C

0  B = A  C

A  C = B

myBytes[i]^ 0x55 =  passBytes[i] 

Vault-door-7

public int[] passwordToIntArray(String hex) {
        int[] x = new int[8];
        byte[] hexBytes = hex.getBytes();
        for (int i=0; i<8; i++) {
            x[i] = hexBytes[i*4]   << 24
                 | hexBytes[i*4+1] << 16
                 | hexBytes[i*4+2] << 8
                 | hexBytes[i*4+3];
        }
        return x;
    }
int[] x = passwordToIntArray(password);
        return x[0] == 1096770097
            && x[1] == 1952395366
            && x[2] == 1600270708
            && x[3] == 1601398833
            && x[4] == 1716808014
            && x[5] == 1734293815
            && x[6] == 1667379558
            && x[7] == 859191138;

common sense?

1 byte = 8 bits

11001110(binary)

CE(hex)

10101100(binary)

AC(hex)

舉個例來看

//when i = 0?

for (int i=0; i<8; i++) {
            x[i] = hexBytes[i*4]   << 24
                 | hexBytes[i*4+1] << 16
                 | hexBytes[i*4+2] << 8
                 | hexBytes[i*4+3];
        }

hexByte[] = {0xA1, 0xB2, 0xC3, 0xD4....}

10100001,11000010,11010011,11100100

10100001,00000000,00000000,00000000

00000000,11000010,00000000,00000000

00000000,00000000,11010011,00000000

10100001,11000010,11010011,11100100

int[] x = passwordToIntArray(password);
        return x[0] == 1096770097
        && x[1] == 1952395366
        && x[2] == 1600270708
        && x[3] == 1601398833
        && x[4] == 1716808014

00000000,00000000,00000000,11100100

現在只知道x[0]的值

因此我們換hex,就可以回推hexbyte裡的內容

x[0] = 0x415f6231
x[1] = 0x745f3066
x[2] = 0x5f623174
x[3] = 0x5f736831
x[4] = 0x6654694e
x[5] = 0x675f3937
x[6] = 0x63623166
x[7] = 0x33363762
0x41,0x5f,0x62,0x31,
0x74,0x5f,0x30,0x66,
0x5f,0x62,0x31,0x74,
0x5f,0x73,0x68,0x31,
0x66,0x54,0x69,0x4e,
0x67,0x5f,0x39,0x37,
0x63,0x62,0x31,0x66,
0x33,0x36,0x37,0x62

就可以換成ASCII了 :)

a = [
1096770097,
1952395366,
1600270708,
1601398833,
1716808014,
1734293815,
1667379558,
859191138
]

b = []

for t in a:
    b.append(str(hex(t)[2::]))

flag = ""
for j in b:
    for i in range(0,len(j),2):
        flag += chr(int('0x'+ j[i] + j[i+1],16))

print(flag)

Vault-door-8

// These pesky special agents keep reverse engineering our source code and then
// breaking into our secret vaults. THIS will teach those sneaky sneaks a
// lesson.
//
// -Minion #0891
import java.util.*; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec;
import java.security.*; class VaultDoor8 {public static void main(String args[]) {
Scanner b = new Scanner(System.in); System.out.print("Enter vault password: ");
String c = b.next(); String f = c.substring(8,c.length()-1); VaultDoor8 a = new VaultDoor8(); if (a.checkPassword(f)) {System.out.println("Access granted."); }
else {System.out.println("Access denied!"); } } public char[] scramble(String password) {/* Scramble a password by transposing pairs of bits. */
char[] a = password.toCharArray(); for (int b=0; b<a.length; b++) {char c = a[b]; c = switchBits(c,1,2); c = switchBits(c,0,3); /* c = switchBits(c,14,3); c = switchBits(c, 2, 0); */ c = switchBits(c,5,6); c = switchBits(c,4,7);
c = switchBits(c,0,1); /* d = switchBits(d, 4, 5); e = switchBits(e, 5, 6); */ c = switchBits(c,3,4); c = switchBits(c,2,5); c = switchBits(c,6,7); a[b] = c; } return a;
} public char switchBits(char c, int p1, int p2) {/* Move the bit in position p1 to position p2, and move the bit
that was in position p2 to position p1. Precondition: p1 < p2 */ char mask1 = (char)(1 << p1);
char mask2 = (char)(1 << p2); /* char mask3 = (char)(1<<p1<<p2); mask1++; mask1--; */ char bit1 = (char)(c & mask1); char bit2 = (char)(c & mask2); /* System.out.println("bit1 " + Integer.toBinaryString(bit1));
System.out.println("bit2 " + Integer.toBinaryString(bit2)); */ char rest = (char)(c & ~(mask1 | mask2)); char shift = (char)(p2 - p1); char result = (char)((bit1<<shift) | (bit2>>shift) | rest); return result;
} public boolean checkPassword(String password) {char[] scrambled = scramble(password); char[] expected = {
0xF4, 0xC0, 0x97, 0xF0, 0x77, 0x97, 0xC0, 0xE4, 0xF0, 0x77, 0xA4, 0xD0, 0xC5, 0x77, 0xF4, 0x86, 0xD0, 0xA5, 0x45, 0x96, 0x27, 0xB5, 0x77, 0xE1, 0xC0, 0xA4, 0x95, 0x94, 0xD1, 0x95, 0x94, 0xD0 }; return Arrays.equals(scrambled, expected); } }

醜爆??????

Best Online Java Viewer

他怎麼switch來,就逆著switch回去

 

int main()
{

    /* Scramble a password by transposing pairs of bits. */

    for (int b = 0; b < 32; b++) {
        int c = a[b];
        c = switchBits(c, 6, 7);
        c = switchBits(c, 2, 5);
        c = switchBits(c, 3, 4);
        c = switchBits(c, 0, 1); /* d = switchBits(d, 4, 5); e = switchBits(e, 5, 6); */
        c = switchBits(c, 4, 7);
        c = switchBits(c, 5, 6);
        c = switchBits(c, 0, 3); /* c = switchBits(c,14,3); c = switchBits(c, 2, 0); */
        c = switchBits(c, 1, 2);
        a[b] = c;
        printf("%c",a[b]);
    }

    return 0;
}
char[] scramble(String password) {
  /* Scramble a password by transposing pairs of bits. */
  char[] a = password.toCharArray();
  for (int b = 0; b < a.length; b++) {
   char c = a[b];
   c = switchBits(c, 1, 2);
   c = switchBits(c, 0, 3); /* c = switchBits(c,14,3); c = switchBits(c, 2, 0); */
   c = switchBits(c, 5, 6);
   c = switchBits(c, 4, 7);
   c = switchBits(c, 0, 1); /* d = switchBits(d, 4, 5); e = switchBits(e, 5, 6); */
   c = switchBits(c, 3, 4);
   c = switchBits(c, 2, 5);
   c = switchBits(c, 6, 7);
   a[b] = c;
  }
  return a;
 }

Payload

int main()
{

    /* Scramble a password by transposing pairs of bits. */

    for (int b = 0; b < 32; b++) {
        int c = a[b];
        c = switchBits(c, 6, 7);
        c = switchBits(c, 2, 5);
        c = switchBits(c, 3, 4);
        c = switchBits(c, 0, 1); /* d = switchBits(d, 4, 5); e = switchBits(e, 5, 6); */
        c = switchBits(c, 4, 7);
        c = switchBits(c, 5, 6);
        c = switchBits(c, 0, 3); /* c = switchBits(c,14,3); c = switchBits(c, 2, 0); */
        c = switchBits(c, 1, 2);
        a[b] = c;
        printf("%c",a[b]);
    }

    return 0;
}
int a[] = {0xF4,0xC0,0x97,0xF0,0x77,0x97,0xC0,0xE4,0xF0,0x77,0xA4,0xD0,0xC5,0x77,0xF4,0x86,0xD0,0xA5,0x45,0x96,0x27,0xB5,0x77,0xE1,0xC0,0xA4,0x95,0x94,0xD1,0x95,0x94,0xD0};
int switchBits(int c, int p1, int p2)
    {
        /* Move the bit in position p1 to position p2, and move the bit
        that was in position p2 to position p1. Precondition: p1 < p2 */
        //int mask1 = (int)(1 << p1);
        //int mask2 = (int)(1 << p2); /* int mask3 = (int)(1<<p1<<p2); mask1++; mask1--; */
        int bit1 = (int)(c & (int)(1 << p1));
        int bit2 = (int)(c & (int)(1 << p2));
        /* System.out.println("bit1 " + Integer.toBinaryString(bit1));
        System.out.println("bit2 " + Integer.toBinaryString(bit2)); */
        int rest = (int)(c & ~((int)(1 << p1) | (int)(1 << p2)));
        int shift = (int)(p2 - p1);
        int result = (int)((bit1 << shift) | (bit2 >> shift) | rest);
        return result;
    }

droids系列題目

建議使用android-studio

還有apktool或者java逆向工具(jadx)

droids:0

apk裝下去及執行,觀察Logcat

droids:1

apktool d <.apk> <folder>

where is password?

droids:1

.line 12
    .local v0, "password":Ljava/lang/String;
    invoke-virtual {p0, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

apktool\one\res\values\strings.xml

droids:2

 public static String getFlag(String input, Context ctx) {
        String[] witches = {"weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"};
        int second = 3 - 3;
        int third = (3 / 3) + second;
        int fourth = (third + third) - second;
        int fifth = 3 + fourth;
        int sixth = (fifth + second) - third;
        String str = ".";
        if (input.equals("".concat(witches[fifth]).concat(str).concat(witches[third]).concat(str).concat(witches[second]).concat(str).concat(witches[sixth]).concat(str).concat(witches[3]).concat(str).concat(witches[fourth]))) {
            return sesame(input);
        }
        return "NOPE";
    }

droids:2

public class FlagstaffHill {
    public static native String sesame(String str);

    public static String getFlag(String input, Context ctx) {
                            //   0            1       2         3        4         5
        String[] witches = {"weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"};
        int second = 0;
        int third = 1;
        int fourth = 2;
        int fifth = 5;
        int sixth = 4;
        String str = ".";
        if (input.equals("".concat(witches[fifth]).concat(str).concat(witches[third]).concat(str).concat(witches[second]).concat(str).concat(witches[sixth]).concat(str).concat(witches[3]).concat(str).concat(witches[fourth]))) {
            return sesame(input);
            //dismass.ogg.weatherwax.aching.nitt.garlick
        }
        return "NOPE";
    }
}

整理後

droids:3

public class FlagstaffHill {
    public static native String cilantro(String str);

    public static String nope(String input) {
        return "don't wanna";
    }

    public static String yep(String input) {
        return cilantro(input);
    }

    public static String getFlag(String input, Context ctx) {
        return nope(input);
    }
}

目標

  • 把getFlag, return的function換成yep

public class FlagstaffHill {
    public static native String cilantro(String str);

    public static String getFlag(String input, Context ctx) {
        return nope(input); - > yep(input);
    }
}

流程

1. apktool逆向出來的code改掉

2. 重新輸出apk

3. apk簽名的keystore

4.在apk上簽名

5. android_studio安裝

apktool b .\three -o three_2.apk
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
jarsigner -verbose -keystore demo.keystore three_2.apk demo.keystore
keytool
-genkey 產生key
-alias 別名
-keystore 指定keystroe名字
-keyalg 密鑰算法
-validity 有效天數
jarsigner
- verbose 詳細輸出
- keystore 證書儲存路徑

Script

public static String getFlag(String input, Context ctx) {
        String str = "aaa";
        StringBuilder ace = new StringBuilder(str);
        StringBuilder jack = new StringBuilder(str);
        StringBuilder queen = new StringBuilder(str);
        StringBuilder king = new StringBuilder(str);
        ace.setCharAt(0, (char) (ace.charAt(0) + 4));
        ace.setCharAt(1, (char) (ace.charAt(1) + 19));
        ace.setCharAt(2, (char) (ace.charAt(2) + 18));
        jack.setCharAt(0, (char) (jack.charAt(0) + 7));
        jack.setCharAt(1, (char) (jack.charAt(1) + 0));
        jack.setCharAt(2, (char) (jack.charAt(2) + 1));
        queen.setCharAt(0, (char) (queen.charAt(0) + 0));
        queen.setCharAt(1, (char) (queen.charAt(1) + 11));
        queen.setCharAt(2, (char) (queen.charAt(2) + 15));
        king.setCharAt(0, (char) (king.charAt(0) + 14));
        king.setCharAt(1, (char) (king.charAt(1) + 20));
        king.setCharAt(2, (char) (king.charAt(2) + 15));
        if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
            return "call it";
        }
        return "NOPE";
    }

droids:4

轉換後

public static String getFlag(String input, Context ctx) {
        String str = "aaa";
        StringBuilder ace = new StringBuilder(str);
        StringBuilder jack = new StringBuilder(str);
        StringBuilder queen = new StringBuilder(str);
        StringBuilder king = new StringBuilder(str);
        ace.setCharAt(0, (char) (a + 4));
        ace.setCharAt(1, (char) (a + 19));
        ace.setCharAt(2, (char) (a + 18));
        jack.setCharAt(0, (char) (a + 7));
        jack.setCharAt(1, (char) (a + 0));
        jack.setCharAt(2, (char) (a + 1));
        queen.setCharAt(0, (char) (a + 0));
        queen.setCharAt(1, (char) (a + 11));
        queen.setCharAt(2, (char) (a + 15));
        king.setCharAt(0, (char) (a + 14));
        king.setCharAt(1, (char) (a + 20));
        king.setCharAt(2, (char) (a + 15));
        if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
            return "call it";
        }
        return "NOPE";
    }

逆完結果

printf("%c",(char)('a' + 0));
printf("%c",(char)('a' + 11));
printf("%c",(char)('a' + 15));
printf("%c",(char)('a' + 7));
printf("%c",(char)('a' + 0));
printf("%c",(char)('a' + 1));
printf("%c",(char)('a' + 4));
printf("%c",(char)('a' + 19));
printf("%c",(char)('a' + 18));
printf("%c",(char)('a' + 14));
printf("%c",(char)('a' + 20));
printf("%c",(char)('a' + 15));
alphabetsoup

觀察function

if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
            return "call it";
        }

成功return call it中間
   執行String cardamom(String str);

改的部分


    if-eqz v5, :cond_0

    const-string v5, "call it"

    invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamom(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v5
    return-object v5

之後步驟跟前題一樣,你可以拿相同的key

asm系列題目

就組語

asm1(0x4f3)

asm1:
	<+0>:	push   ebp
	<+1>:	mov    ebp,esp
	<+3>:	cmp    DWORD PTR [ebp+0x8],0x45d
	<+10>:	jg     0x512 <asm1+37>
	<+12>:	cmp    DWORD PTR [ebp+0x8],0x430
	<+19>:	jne    0x50a <asm1+29>
	<+21>:	mov    eax,DWORD PTR [ebp+0x8]
	<+24>:	add    eax,0x17
	<+27>:	jmp    0x529 <asm1+60>
	<+29>:	mov    eax,DWORD PTR [ebp+0x8]
	<+32>:	sub    eax,0x17
	<+35>:	jmp    0x529 <asm1+60>
	<+37>:	cmp    DWORD PTR [ebp+0x8],0x7cd
	<+44>:	jne    0x523 <asm1+54>
	<+46>:	mov    eax,DWORD PTR [ebp+0x8]
	<+49>:	sub    eax,0x17
	<+52>:	jmp    0x529 <asm1+60>
	<+54>:	mov    eax,DWORD PTR [ebp+0x8]
	<+57>:	add    eax,0x17
	<+60>:	pop    ebp
	<+61>:	ret    

asm1(0x4f3)

0x4f3
ret
ebp <- esp
<+0>:	push   ebp
<+1>:	mov    ebp,esp
<+3>:	cmp    DWORD PTR [ebp+0x8],0x45d
<+10>:	jg     0x512 <asm1+37>

0x4f3 > 0x45d?

asm1(0x4f3)

0x4f3
ret
ebp <- esp
<+37>:	cmp    DWORD PTR [ebp+0x8],0x7cd
<+44>:	jne    0x523 <asm1+54>

0x4f3 != 0x477 ?

asm1(0x4f3)

0x4f3
ret
ebp <- esp
<+54>:	mov    eax,DWORD PTR [ebp+0x8]
<+57>:	add    eax,0x17
<+60>:	pop    ebp
<+61>:	ret    

0x4f3 + 0x17 ?

asm2(0xe, 0x22)

asm2:
	<+0>:	push   ebp
	<+1>:	mov    ebp,esp
	<+3>:	sub    esp,0x10
	<+6>:	mov    eax,DWORD PTR [ebp+0xc]
	<+9>:	mov    DWORD PTR [ebp-0x4],eax
	<+12>:	mov    eax,DWORD PTR [ebp+0x8]
	<+15>:	mov    DWORD PTR [ebp-0x8],eax
	<+18>:	jmp    0x50c <asm2+31>
	<+20>:	add    DWORD PTR [ebp-0x4],0x1
	<+24>:	add    DWORD PTR [ebp-0x8],0xd1
	<+31>:	cmp    DWORD PTR [ebp-0x8],0x9087
	<+38>:	jle    0x501 <asm2+20>
	<+40>:	mov    eax,DWORD PTR [ebp-0x4]
	<+43>:	leave  
	<+44>:	ret    

function-push

void func()
{
	myfun(1,2,3);
}
3
2
1

asm2(0xe, 0x22)

0x22 <-ebp+12
0xe <-ebp+8
ret <-ebp+4
ebp
<+6>:   mov    eax,DWORD PTR [ebp+0xc]
<+9>:   mov    DWORD PTR [ebp-0x4],eax
0x22 <-ebp-4

asm2(0xe, 0x22)

0x22 <-ebp+12
0xe <-ebp+8
ret <-ebp+4
ebp
<+12>:  mov    eax,DWORD PTR [ebp+0x8]
<+15>:  mov    DWORD PTR [ebp-0x8],eax
<+18>:  jmp    0x50c <asm2+31>
0x22 <-ebp-4
0xe <-ebp-8

asm2(0xe, 0x22)

0x22 <-ebp-4
0xe <-ebp-8
<+18>:	jmp    0x50c <asm2+31>
<+20>:	add    DWORD PTR [ebp-0x4],0x1
<+24>:	add    DWORD PTR [ebp-0x8],0xd1
<+31>:	cmp    DWORD PTR [ebp-0x8],0x9087
<+38>:	jle    0x501 <asm2+20>
<+40>:	mov    eax,DWORD PTR [ebp-0x4]
0xe + 0xd1 * n > 0x9087
n+0x22

asm3(0xcdc485c1,0xd6bd5e88,0xe4c1548d)

asm3:
	<+0>:	push   ebp
	<+1>:	mov    ebp,esp
	<+3>:	xor    eax,eax
	<+5>:	mov    ah,BYTE PTR [ebp+0x8]
	<+8>:	shl    ax,0x10
	<+12>:	sub    al,BYTE PTR [ebp+0xe]
	<+15>:	add    ah,BYTE PTR [ebp+0xc]
	<+18>:	xor    ax,WORD PTR [ebp+0x10]
	<+22>:	nop
	<+23>:	pop    ebp
	<+24>:	ret    

Little-endian

3 0xDE
2 0xAD
1 0xBE
0 0xEF

0xDEADBEEF

stack

0xe4c1548d ebp+0xF
0xd6bd5e88 ebp+0xc
0xcdc485c1 ebp+8
ret ebp+4
ebp

asm3(0xcdc485c1,0xd6bd5e88,0xe4c1548d)

+8

+9

+A

+B

code

asm3(0xcdc485c1,0xd6bd5e88,0xe4c1548d)

<+0>:	push   ebp
<+1>:	mov    ebp,esp
<+3>:	xor    eax,eax
<+5>:	mov    ah,BYTE PTR [ebp+0x8]
<+8>:	shl    ax,0x10
<+12>:	sub    al,BYTE PTR [ebp+0xe]
<+15>:	add    ah,BYTE PTR [ebp+0xc]
<+18>:	xor    ax,WORD PTR [ebp+0x10]
<+22>:	nop
<+23>:	pop    ebp
<+24>:	ret

asm4

asm4:
	<+0>:	push   ebp
	<+1>:	mov    ebp,esp
	<+3>:	push   ebx
	<+4>:	sub    esp,0x10
	<+7>:	mov    DWORD PTR [ebp-0x10],0x276
	<+14>:	mov    DWORD PTR [ebp-0xc],0x0
	<+21>:	jmp    0x518 <asm4+27>
	<+23>:	add    DWORD PTR [ebp-0xc],0x1
	<+27>:	mov    edx,DWORD PTR [ebp-0xc]
	<+30>:	mov    eax,DWORD PTR [ebp+0x8]
	<+33>:	add    eax,edx
	<+35>:	movzx  eax,BYTE PTR [eax]
	<+38>:	test   al,al
	<+40>:	jne    0x514 <asm4+23>
	<+42>:	mov    DWORD PTR [ebp-0x8],0x1
	<+49>:	jmp    0x587 <asm4+138>
	<+51>:	mov    edx,DWORD PTR [ebp-0x8]
	<+54>:	mov    eax,DWORD PTR [ebp+0x8]
	<+57>:	add    eax,edx
	<+59>:	movzx  eax,BYTE PTR [eax]
	<+62>:	movsx  edx,al
	<+65>:	mov    eax,DWORD PTR [ebp-0x8]
	<+68>:	lea    ecx,[eax-0x1]
	<+71>:	mov    eax,DWORD PTR [ebp+0x8]
	<+74>:	add    eax,ecx
	<+76>:	movzx  eax,BYTE PTR [eax]
	<+79>:	movsx  eax,al
	<+82>:	sub    edx,eax
	<+84>:	mov    eax,edx
	<+86>:	mov    edx,eax
	<+88>:	mov    eax,DWORD PTR [ebp-0x10]
	<+91>:	lea    ebx,[edx+eax*1]
	<+94>:	mov    eax,DWORD PTR [ebp-0x8]
	<+97>:	lea    edx,[eax+0x1]
	<+100>:	mov    eax,DWORD PTR [ebp+0x8]
	<+103>:	add    eax,edx
	<+105>:	movzx  eax,BYTE PTR [eax]
	<+108>:	movsx  edx,al
	<+111>:	mov    ecx,DWORD PTR [ebp-0x8]
	<+114>:	mov    eax,DWORD PTR [ebp+0x8]
	<+117>:	add    eax,ecx
	<+119>:	movzx  eax,BYTE PTR [eax]
	<+122>:	movsx  eax,al
	<+125>:	sub    edx,eax
	<+127>:	mov    eax,edx
	<+129>:	add    eax,ebx
	<+131>:	mov    DWORD PTR [ebp-0x10],eax
	<+134>:	add    DWORD PTR [ebp-0x8],0x1
	<+138>:	mov    eax,DWORD PTR [ebp-0xc]
	<+141>:	sub    eax,0x1
	<+144>:	cmp    DWORD PTR [ebp-0x8],eax
	<+147>:	jl     0x530 <asm4+51>
	<+149>:	mov    eax,DWORD PTR [ebp-0x10]
	<+152>:	add    esp,0x10
	<+155>:	pop    ebx
	<+156>:	pop    ebp
	<+157>:	ret

無腦法

1. 寫一個c把asm4("picoCTF_75806")把生.obj

2.另一組語那包也用gcc編譯成.obj

3.把兩個.obj連起來輸出並執行

無腦法

-m32   Compile 32 bits objects on a compiler

-c         Compile and assemble, but do not link.
gcc -m32 -c asm4.S -o asm4_asm.o
gcc -m32 -c asm4.c -o asm4_print.o
gcc -m32 -o a.out asm4_asm.o asm4_print.o ./a.out

binary系列題目

ghidra

ida

gdb

reverse_cipher

for ( i = 0; i <= 7; ++i )
  {
    v11 = ptr[i];
    fputc(v11, v7);
  }
  for ( j = 8; j <= 22; ++j )
  {
    v11 = ptr[j];
    if ( j & 1 )
      v11 -= 2;
    else
      v11 += 5;
    fputc(v11, v7);
  }

j=8之後是-2,+5

改成+2,-5就能回推字串

Time's Up

執行他之後,程式會要求在時間內算很長的一段算式

算成功就會去叫flag.txt

Script

from pwn import *

p = process("/problems/time-s-up_3_37ba6326d772bf884eab8f28e480e580/times-up", cwd='/problems/time-s-up_3_37ba6326d772bf884eab8f28e480e580')
question = p.readuntil("\n").split(":")[1]
p.sendline(str(eval(question)))
p.interactive()

Need For Speed

int __cdecl main(int argc, const char **argv, const char **envp)
{
  header();
  set_timer();
  get_key();
  print_flag();
  return 0;
}

繞過set_timer??

Time's Up, Again!

????????

Made with Slides.com