일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- picoCTF
- Cube Root Attack
- RSA Common Modulas Attack
- overthewire
- XSS
- Franklin-Reiter Related Message Attack
- CSRF
- 시스템해킹
- pycrpytodome
- OverTheWire Bandit Level 1 → Level 2
- Montgomery Reduction
- arp
- cryptography
- dns
- Bandit Level 1 → Level 2
- 웹해킹
- 암호학
- return address overflow
- bandit
- rao
- weak key
- shellcode
- Hastad
- dreamhack
- 드림핵
- Crypto
- AES
- RSA
- spoofing
- redirect
- Today
- Total
암호(수학) 등.. 공부한 거 잊을거 같아서 만든 블로그
[Dreamhack] funjs 본문
문제
문제 파일 : index.html
<html>
<head>
<style>*{margin: 0;}</style>
<script>
var box;
window.onload = init;
function init() {
box = document.getElementById("formbox");
setInterval(moveBox,1000);
}
// function moveBox() {
// box.posX = Math.random() * (window.innerWidth - 64);
// box.posY = Math.random() * (document.documentElement.scrollHeight - 64);
// box.style.marginLeft = box.posX + "px";
// box.style.marginTop = box.posY + "px";
// debugger;
// }
function text2img(text){
var imglist = box.getElementsByTagName('img');
while(imglist.length > 0) {imglist[0].remove();}
var canvas = document.createElement("canvas");
canvas.width = 620;
canvas.height = 80;
var ctx = canvas.getContext('2d');
ctx.font = "30px Arial";
var text = text;
ctx.fillText(text,10,50);
var img = document.createElement("img");
img.src = canvas.toDataURL();
box.append(img);
};
function main(){
var _0x1046=['2XStRDS','1388249ruyIdZ','length','23461saqTxt','9966Ahatiq','1824773xMtSgK','1918853csBQfH','175TzWLTY','flag','getElementById','94hQzdTH','NOP\x20!','11sVVyAj','37594TRDRWW','charCodeAt','296569AQCpHt','fromCharCode','1aqTvAU'];
var _0x376c = function(_0xed94a5, _0xba8f0f) {
_0xed94a5 = _0xed94a5 - 0x175;
var _0x1046bc = _0x1046[_0xed94a5];
return _0x1046bc;
};
var _0x374fd6 = _0x376c;
(function(_0x24638d, _0x413a92) {
var _0x138062 = _0x376c;
while (!![]) {
try {
var _0x41a76b = -parseInt(_0x138062(0x17f)) + parseInt(_0x138062(0x180)) * -parseInt(_0x138062(0x179)) + -parseInt(_0x138062(0x181)) * -parseInt(_0x138062(0x17e)) + -parseInt(_0x138062(0x17b)) + -parseInt(_0x138062(0x177)) * -parseInt(_0x138062(0x17a)) + -parseInt(_0x138062(0x17d)) * -parseInt(_0x138062(0x186)) + -parseInt(_0x138062(0x175)) * -parseInt(_0x138062(0x184));
if (_0x41a76b === _0x413a92) break;
else _0x24638d['push'](_0x24638d['shift']());
} catch (_0x114389) {
_0x24638d['push'](_0x24638d['shift']());
}
}
}(_0x1046, 0xf3764));
var flag = document[_0x374fd6(0x183)](_0x374fd6(0x182))['value'],
_0x4949 = [0x20, 0x5e, 0x7b, 0xd2, 0x59, 0xb1, 0x34, 0x72, 0x1b, 0x69, 0x61, 0x3c, 0x11, 0x35, 0x65, 0x80, 0x9, 0x9d, 0x9, 0x3d, 0x22, 0x7b, 0x1, 0x9d, 0x59, 0xaa, 0x2, 0x6a, 0x53, 0xa7, 0xb, 0xcd, 0x25, 0xdf, 0x1, 0x9c],
_0x42931 = [0x24, 0x16, 0x1, 0xb1, 0xd, 0x4d, 0x1, 0x13, 0x1c, 0x32, 0x1, 0xc, 0x20, 0x2, 0x1, 0xe1, 0x2d, 0x6c, 0x6, 0x59, 0x11, 0x17, 0x35, 0xfe, 0xa, 0x7a, 0x32, 0xe, 0x13, 0x6f, 0x5, 0xae, 0xc, 0x7a, 0x61, 0xe1],
operator = [(_0x3a6862, _0x4b2b8f) => {
return _0x3a6862 + _0x4b2b8f;
}, (_0xa50264, _0x1fa25c) => {
return _0xa50264 - _0x1fa25c;
}, (_0x3d7732, _0x48e1e0) => {
return _0x3d7732 * _0x48e1e0;
}, (_0x32aa3b, _0x53e3ec) => {
return _0x32aa3b ^ _0x53e3ec;
}],
getchar = String[_0x374fd6(0x178)];
if (flag[_0x374fd6(0x17c)] != 0x24) {
text2img(_0x374fd6(0x185));
return;
}
for (var i = 0x0; i < flag[_0x374fd6(0x17c)]; i++) {
if (flag[_0x374fd6(0x176)](i) == operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i])) {} else {
text2img(_0x374fd6(0x185));
return;
}
}
text2img(flag);
}
</script>
</head>
<body>
<div id='formbox'>
<h2>Find FLAG !</h2>
<input type='flag' id='flag' value=''>
<input type='button' value='submit' onclick='main()'>
</div>
</body>
</html>
풀이
웹페이지를 키면 입력창이 계속 움직인다.
일단 코드를 확인해 보면
function moveBox() {
box.posX = Math.random() * (window.innerWidth - 64);
box.posY = Math.random() * (document.documentElement.scrollHeight - 64);
box.style.marginLeft = box.posX + "px";
box.style.marginTop = box.posY + "px";
debugger;
}
이 부분때문에 움직이는 것을 알 수 있다.
또한 debugger; 때문에 디버거가 활성화 된다.
분석에 방해되고 필요 없으므로 주석처리하자.
입력값을 검증 하여 flag가 아니라면 NOP ! 을 출력해준다.
코드를 보면 NOP ! 을 출력해주는 함수가 text2img 함수인 것을 이름을 보고 짐작할 수 있고, 함수에 브레이킹 포인트를 걸고 디버깅을 해보면 알 수 있다.
function text2img(text){
var imglist = box.getElementsByTagName('img');
while(imglist.length > 0) {imglist[0].remove();}
var canvas = document.createElement("canvas");
canvas.width = 620;
canvas.height = 80;
var ctx = canvas.getContext('2d');
ctx.font = "30px Arial";
var text = text;
ctx.fillText(text,10,50);
var img = document.createElement("img");
img.src = canvas.toDataURL();
box.append(img);
};
위 코드를 제외한 코드는 난독화가 되어 있다. 따라서 일단 a를 입력해서 디버깅을 해보면, 아래 코드의 첫번째 if 문에서 true가 되어 NOP !를 출력하고 리턴 하는 것을 알 수 있다. 또한 flag 변수가 입력값임을 알 수 있다.
if (flag[_0x374fd6(0x17c)] != 0x24) {
text2img(_0x374fd6(0x185));
return;
}
for (var i = 0x0; i < flag[_0x374fd6(0x17c)]; i++) {
if (flag[_0x374fd6(0x176)](i) == operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i])) {} else {
text2img(_0x374fd6(0x185));
return;
}
}
text2img(flag);
}
그러면 _0x373fd6이 뭐하는 함수인지 디버깅을 통해 알아보자.
일단 코드만을 본다면 _0x373fd6 가 _0x376c 임을 알 수 있다.
var _0x376c = function(_0xed94a5, _0xba8f0f) {
_0xed94a5 = _0xed94a5 - 0x175;
var _0x1046bc = _0x1046[_0xed94a5];
return _0x1046bc;
};
var _0x374fd6 = _0x376c;
_0x376c 에 브레이킹 포인트를 걸어서 디버깅을 하면
_0x376c의 인자인 _0xed94a5의 값이 _0x374fd6(0x17c) 의 매개변수 값임을 알 수 있다. ( 0x17c = 383 )
따라서 return 값은 _0x1046[0x17c - 0x 175] = _0x1046[7] 가 된다.
var _0x1046=['2XStRDS','1388249ruyIdZ','length','23461saqTxt','9966Ahatiq','1824773xMtSgK','1918853csBQfH','175TzWLTY','flag','getElementById','94hQzdTH','NOP\x20!','11sVVyAj','37594TRDRWW','charCodeAt','296569AQCpHt','fromCharCode','1aqTvAU'];
배열의 값은 위와 같은데 무슨이유인지는 모르겠지만 vscode를 이용하여 인덱스별 값을 확인해보면 위와는 다르게 순서가 뒤죽박죽이다.
일단 _0x1046[7] = 'length' 이므로 flag[_0x374fd6(0x176)] 는 flag의 길이를 구하는 함수임을 생각해 볼 수 있다.
따라서 flag[_0x374fd6(0x176)] != 0x24 이므로 입력값의 길이가 0x24 = 36 이 되도록 넣어보면 첫번째 if 문을 통과하여 넘어가는 것을 디버깅을 통해 확인 할 수 있다.
이제 두번째 if 문을 보자.
for (var i = 0x0; i < flag[_0x374fd6(0x17c)]; i++) {
if (flag[_0x374fd6(0x176)](i) == operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i])) {} else {
text2img(_0x374fd6(0x185));
return;
}
}
text2img(flag);
}
flag의 길이 만큼 반복하여 if문이 실행되고 있다.
if 문을 자세히 보면 flag[_0x374fd6(0x176)](i) 의 값과 operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i]) 의 값을 비교하여 틀리면 NOP ! 를 출력한 후 return 하고, 전부 일치하면 flag를 출력한다.
따라서 operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i]) 의 값을 구하면 flag의 값을 알 수 있을 것이다.
if 문에서 아래 코드 부분을 보자
operator[i % operator[_0x374fd6(0x17c)]](_0x4949[i], _0x42931[i])
operator 는 매개변수로 두 배열을 넘겨주고 있다.
_0x4949 = [0x20, 0x5e, 0x7b, 0xd2, 0x59, 0xb1, 0x34, 0x72, 0x1b, 0x69, 0x61, 0x3c, 0x11, 0x35, 0x65, 0x80, 0x9, 0x9d, 0x9, 0x3d, 0x22, 0x7b, 0x1, 0x9d, 0x59, 0xaa, 0x2, 0x6a, 0x53, 0xa7, 0xb, 0xcd, 0x25, 0xdf, 0x1, 0x9c],
_0x42931 = [0x24, 0x16, 0x1, 0xb1, 0xd, 0x4d, 0x1, 0x13, 0x1c, 0x32, 0x1, 0xc, 0x20, 0x2, 0x1, 0xe1, 0x2d, 0x6c, 0x6, 0x59, 0x11, 0x17, 0x35, 0xfe, 0xa, 0x7a, 0x32, 0xe, 0x13, 0x6f, 0x5, 0xae, 0xc, 0x7a, 0x61, 0xe1],
operator = [(_0x3a6862, _0x4b2b8f) => {
return _0x3a6862 + _0x4b2b8f;
}, (_0xa50264, _0x1fa25c) => {
return _0xa50264 - _0x1fa25c;
}, (_0x3d7732, _0x48e1e0) => {
return _0x3d7732 * _0x48e1e0;
}, (_0x32aa3b, _0x53e3ec) => {
return _0x32aa3b ^ _0x53e3ec;
}],
operator 를 보면 인덱스에 따라 동작이 다르다 ( 0 : '+ ' , 1: '-' , 2 : '*' , 3 : '^' )
operator[i % operator[_0x374fd6(0x17c)]]
즉 0x374fd6(0x17c) 의 값에 따라 적용하는 연산 방식이 다르다.
근데 우리는 0x374fd6(0x17c)이 length를 의미함을 첫번째 if 문에서 알아냈기 때문에 operator의 크기인 operator[0x374fd6(0x17c)] = 4 임을 알 수 있다.
따라서 연산 방식은 +, -, *, ^ 순으로 ( 0, 1, 2, 3, 0, 1, 2, 3.....) 진행되므로 파이썬을 이용하여 두 배열에 연산을 적용해보면
flag 를 구할 수 있다.
exploit.py
arr1 = [0x20, 0x5e, 0x7b, 0xd2, 0x59, 0xb1, 0x34, 0x72, 0x1b, 0x69, 0x61, 0x3c, 0x11, 0x35, 0x65, 0x80, 0x9,
0x9d, 0x9, 0x3d, 0x22, 0x7b, 0x1, 0x9d, 0x59, 0xaa, 0x2, 0x6a, 0x53, 0xa7, 0xb, 0xcd, 0x25, 0xdf, 0x1, 0x9c]
arr2 = [0x24, 0x16, 0x1, 0xb1, 0xd, 0x4d, 0x1, 0x13, 0x1c, 0x32, 0x1, 0xc, 0x20, 0x2, 0x1, 0xe1, 0x2d, 0x6c,
0x6, 0x59, 0x11, 0x17, 0x35, 0xfe, 0xa, 0x7a, 0x32, 0xe, 0x13, 0x6f, 0x5, 0xae, 0xc, 0x7a, 0x61, 0xe1]
result = ''
for i in range(len(arr1)):
if i % 4 == 0:
result += chr(arr1[i] + arr2[i])
elif i % 4 == 1:
result += chr(arr1[i] - arr2[i])
elif i % 4 == 2:
result += chr(arr1[i] * arr2[i])
elif i % 4 == 3:
result += chr(arr1[i] ^ arr2[i])
print(result)
'Dreamhack > Web' 카테고리의 다른 글
[Dreamhack] xss-2 (0) | 2023.04.08 |
---|---|
[Dreamhack] xss-1 (0) | 2023.04.07 |
[Dreamhack] cookie (0) | 2023.04.04 |
[Dreamhack] session-basic (0) | 2023.04.04 |
[Dreamhack] Carve Party (0) | 2023.04.03 |