반응형
JSFuck은 난해한 프로그래밍 스타일의 하나로, 오로지 ( ) [ ] + ! 라는 6가지의 문자만 써서 JavaScript의 코드를 구현한다. Martin Kleppe가 개발하였으며 자바스크립트를 해석하는 어떠한 웹 브라우저나 엔진에서라도 실행할 수 있다.
- Encoding 사이트 참고 : https://jsfuck.com
JSFuck - Write any JavaScript with 6 Characters: []()!+
jsfuck.com
그렇다면, 해당 문자를 이용해서 함수 실행을 어떻게 할지 단계별로 살펴보자.
1단계: 기본 Boolean값 만들기
- JavaScript에서 빈 배열 []은 truthy이지만, 부정연산자 !를 쓰면 false가 된다.
- [] // 빈 배열 (truthy)
- ![] // false (배열을 부정)
- !![] // true (이중 부정)
2단계: 숫자 생성
- + 연산자는 값을 숫자로 강제 변환한다. 빈 배열은 0, false도 0이 된다.
- +[] // 0 (빈 배열을 숫자로 변환)
- +![] // 1 (false를 숫자로 변환하면 0, 이를 부정하면 1)
- !+[]+!+[] // 2 (1 + 1)
3단계: 기본 문자열 생성
- 배열과 다른 값을 +로 연산하면 문자열 연결이 된다.
- ![] + [] // "false" (false + 빈배열 = 문자열 "false")
- !![] + [] // "true"
- [][+[]] // undefined (배열의 0번째 요소, 없으므로 undefined)
- [][+[]] + [] // "undefined" (undefined를 문자열로 변환)
4단계: 개별 문자 추출
- 문자열에서 [인덱스]로 문자를 뽑아낸다.
- (![] + [])[+[]] // "false"[0] = "f"
- (![] + [])[+!+[]] // "false"[1] = "a"
- (![] + [])[!+[]+!+[]] // "false"[2] = "l"
- (!![] + [])[+[]] // "true"[0] = "t"
- (!![] + [])[+!+[]] // "true"[1] = "r"
- 여기서 +[]는 0, +!+[]는 1, !+[]+!+[]는 2입니다.
5단계: 더 많은 문자 얻기
- 객체 문자열 활용
- {} + [] // "[object Object]"
- ({} + [])[+!+[]] // "o" (object의 o)
- ({} + [])[!+[]+!+[]] // "b" (object의 b)
6단계: 함수 호출
- 브라우저에서 alert(1)을 호출하는 JSFuck 문자열:
- [][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[+!+[]]]+[+!+[]]+([]+[]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[!+[]+!+[]]])
- 어떤식으로 구현한 것일까?
- 위 문자열은, [][at][constructor]("alert(1)")() 문자열을 JSFuck Encoding한 것이다.
- 그렇다면 구문별로 그 의미를 분석해보자.
- [][at]은 Array.prototype.at 함수이다. 그 함수가 어떤 함수인지는 중요치 않다.
- 여기에 constructor를 더한다는 것은, Array.prototype.at의 constructor(생성자)를 의미하며, 모든 함수의 constructor는 Function이다. 그리고 Function constructor는 문자열로 함수를 생성한다.
- 이를 통해 [][at][constructor]("alert(1)")() 의 변환 과정을 보면 아래와 같이 4단계로 설며할 수 있다.
| 1. 일반 문자열 | [][at][constructor]("alert(1)")() |
| 2. 실제 의미 | Array.prototype.at.constructor("alert(1)")() |
| 3. 핵심 동작 | Function("alert(1)")() |
| 4. 최종 실행 | alert(1) |
- 결국, at이라는 함수는 단순히 Fucntion을 불러오기 위한 매개체일 뿐 다른함수가 사용되어도 동일하다.
* 핵심 원리 정리
- 타입 강제변환: JavaScript의 자동 타입 변환 활용
- 문자열 인덱싱: "문자열"[숫자]로 개별 문자 추출
- 기본 문자열들: "false", "true", "undefined", "[object Object]", "NaN" 등
- 조합: 기존 문자들을 +로 연결해서 새로운 문자열 생성
- 동적 프로퍼티 접근: obj[문자열]로 메서드나 프로퍼티 접근
- 이런 식으로 6개 문자([]()!+)만으로도 JavaScript의 모든 기능에 접근할 수 있습니다. 하지만 코드가 기하급수적으로 길어져서 실용성은 전혀 없다.
반응형
'보안' 카테고리의 다른 글
| ASP.NET 웹쉘(Webshell) 코드 분석 (2) | 2025.01.29 |
|---|---|
| NXDomain(Non-eXistent Domain)을 이용한 DNS 공격 - NXDomain Flooding Attack, Subdomain Scanning Attack (1) | 2024.07.10 |