바킹독의 실전 알고리즘 : 오티

환경설정

#include <bits/stdc++.h>

코테에서 많이 쓰는 라이브러리를 bits 폴더 안에 넣는다는 코드이다. 이 헤더는 gcc에만 있기 때문에 Visual Studio 2017/2019에서는 따로 폴더에 넣어줘야 한다. 몇몇 시험장에서는 위 헤더를 못쓰게 한다고 한다. 아래 대표 헤더들은 외우자.

#include <iostream>
#include <string>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <functional>
#include <algorithm>

맥에서 cpp 구동

난 mac이니까 따로 세팅을 해줘야 한다.

참고한 글

실행해보니 이미 여기까지는 구축을 해둔 거 같다.

근데 bits/stdc++.h가 안 먹는다. mac 환경이라서 그런듯

참고한 글

6kiity@yug-eunseoui-MacBookAir algo % g++ --version
Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: arm64-apple-darwin25.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin # 이 위치로 분기 
6kiity@yug-eunseoui-MacBookAir algo % cd /Library/Developer/CommandLineTools/usr/
6kiity@yug-eunseoui-MacBookAir usr % ls
bin     include lib     libexec share
6kiity@yug-eunseoui-MacBookAir usr % cd include
6kiity@yug-eunseoui-MacBookAir include % open .

mkdir로 bits 폴더를 만들어준다. 난 GUI에서 만들었다.

6kiity@yug-eunseoui-MacBookAir include % cd bits
6kiity@yug-eunseoui-MacBookAir bits % vi stdc++.h
6kiity@yug-eunseoui-MacBookAir bits % code stdc++.h

위 글을 참고해서 설정해보자

#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

  // C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator> 
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

code stdc++.h에서 처음에 안 먹혀서 code 명령어도 설치해줬다.

참고한 글

cmd+shift+p 누르고 Shell command: install ‘code’ command in PATH 하면 알아서 깔아진다.

[WebHacking.kr] old-54번 문제 풀이 (Write-up)

Web2/old-54 문제

자바스크립트의 동작 방식을 분석 -> 로직을 수정하여 실행하는 Client side scripting 문제

  1. 문제 분석 (Analysis)

f12로 소스 코드를 확인 src/script.js

function run(){
  if(window.ActiveXObject){
   try {
    return new ActiveXObject('Msxml2.XMLHTTP');
   } catch (e) {
    try {
     return new ActiveXObject('Microsoft.XMLHTTP');
    } catch (e) {
     return null;
    }
   }
  }else if(window.XMLHttpRequest){
   return new XMLHttpRequest();

  }else{
   return null;
  }
}

x=run();

function answer(i){
  x.open('GET','?m='+i,false);
  x.send(null);
  aview.innerHTML=x.responseText;
  i++;
  if(x.responseText) setTimeout("answer("+i+")",20);
  if(x.responseText=="") aview.innerHTML="?";
}

setTimeout("answer(0)",1000);

answer(i) 함수가 핵심적인 역할이다.

XMLHttpRequest 객체를 생성 -> ?m=i 파라미터를 통해 서버에 요청을 보냄 -> 여기서 i는 0부터 1씩 증가한다.

서버로부터 받은 응답(x.responseText)을 aview.innerHTML에 덮어쓴다.

응답 값이 존재하면 20ms 뒤에 i를 1 증가시켜 재귀적으로 answer 함수를 호출한다.

  1. 익스플로잇

overwrite 말고 concatenate로 출력 로직 변경

var merged = '';
var i = 0;
var xhr = new XMLHttpRequest();

// 무한 루프를 돌며 순차적으로 요청을 보냄
while(true) {
  // 동기(false) 방식으로 요청하여 순서 보장
  xhr.open('GET', '?m=' + i, false);
  xhr.send(null);

  // 응답이 없으면(플래그 끝) 반복 종료
  if(!xhr.responseText) break;

  // 응답 받은 글자를 누적
  merged += xhr.responseText;
  i++;
}

// 결과 출력
console.log("FLAG:", merged);
alert(merged);

코드 설명:

while(true) 문을 사용하여 계속해서 요청을 보낸다.

xhr.open의 세 번째 인자를 false로 설정하여 동기(Synchronous)로 설정해야 응답이 올 때까지 대기(만약에 비동기로 설정하면 응답 수신을 생각 안 하고 다음 명령으로 넘어갈 수 있으므로 오류날 수 있다)

merged += xhr.responseText를 통해 한 글자씩 받은 데이터를 계속 이어 붙인다.

서버에서 더 이상 문자를 반환하지 않으면 break로 루프를 탈출하고 완성된 문자열을 출력한다.

XMLHttpRequest의 open()함수의 인자 설명

  1. http 메서드 지정( get 혹은 post)
  2. 접속할 url을 입력한다
  3. true가 비동기, false가 동기 ```

aml 공통세션

1. stolen funds 신고 프로세스

1. Stop the bleeding :

  1. revoke.cash 또는 etherscan의 토큰 승인 도구로 권한들을 취소한다
  2. 접근 권한 탈취 가능성이 있으므로 새 지갑 생성 후 자산 이동
  3. 이후 지갑과 연결된 거래소 계정을 동결한다.
    1. 연결된 CEX 계정 인출 비활성화
    2. 비밀번호 변경
    3. 2FA

2. Document everything

  • 트랜잭션 해시(TxID): 모든 스마트 컨트랙트 상호작용 기록
  • 공격자 지갑 주소: 자금이 최종 이동한 주소
  • 블록 탐색기 스크린샷: Etherscan, BscScan 등에서의 트랜잭션 내역 (트랜잭션 타임스탬프, 금액, 중개 주소 포함 (휘발성 때문에 즉시 캡처)
  • 이외에 취약점 해킹이라면 컨트랙트 주소, 피싱 링크 스크린샷 등등

3. reporting

  1. CEX 유입 모니터링 : traceable한 거래소라면 Stolen Funds Report 제출
  2. 필요 시 국가 규제기관 신고
  3. 이더스캔의 report/flag address 활용

4. Track the stolen funds

  1. scan 사이트를 활용하여 CEX 유입 확인
  2. KYC 적용된 거래소일 시 법 집행 기관이 계정 동결 요청

+) etherscan report/flag 절차

image.png

  1. 사기 주소(지갑 혹 컨트랙트)에서 More > Report/Flag Address
  2. 아래 양식 작성
What is the phishing address?
(Required)

Link to the screenshot (proof of scam)
(Required)

If is a phishing link, what is the URL?
(Optional)

If above is true, what is the actual link?
(Optional)
  1. 검토 후 Warning! 표시

image.png

+) stolen funds report 예시

MEXC에 따로 사이트가 있어서 가져왔습니다

Report abnormal funds

image.png

스크린샷 2025-11-03 오후 3.18.57.png

스크린샷 2025-11-03 오후 3.19.12.png

Law Enforcement Requests

스크린샷 2025-11-03 오후 3.23.26.png

스크린샷 2025-11-03 오후 3.23.43.png

스크린샷 2025-11-03 오후 3.24.24.png

+) Stolen fund의 destination

https://www.chainalysis.com/blog/2025-crypto-crime-mid-year-update/

https://www.chainalysis.com/blog/2025-crypto-crime-mid-year-update/

funds stolen from personal wallets tend to interact more with token smart contracts (potentially suggesting a swap); send value into sanctioned entities (notably Garantex), which might suggest a Russian perpetrator intersection; and flow to centralized exchanges (CEXs), suggesting less sophisticated laundering techniques.

2. DeFi AML/KYC 준수의 어려움

DeFi의 규제 관할

DeFi 구조 : 비수탁, 스마트컨트랙트 → 중앙 관리자가 없다는 점이 갖고 있는 두 가지 문제점

  1. DEX 또한 VASP를 정의해야 한다지만 모호
  2. 통제권을 갖고 있는 사람, 서비스가 없어 자산 동결 불가능

FATF는 ‘DEX도 VASP(가상자산 서비스 제공자)로 간주할 수 있다’는 입장을 제시했지만, ‘탈중앙화 수준에 따라 적용 범위가 달라질 수 있다’는 점에서 아직 명확한 가이드라인이 부족

실제로도 SEC에서 Uniswap을 포함한 13개 암호화폐 기업에 Wells notice를 발송 → 하지만 Uniswap은 별다른 조치 없이 조사 종결

law 칼럼에서는 이러한 이유를 비수탁형 모델이고, 탈중앙화 프로토콜이기에 SEC의 관할권이라고 보기 어려운 법적 근거가 될 수 있다고 작성함

스크린샷 2025-11-03 오전 1.05.08.png

단순히 면죄부를 준 것은 아님(위 기사 헤드라인을 보면 decentralized crypto platforms도 exchanges로 간주함) → 그저 DeFi에 대한 AML/KYC 규제가 명확하지 않아 불안정한 상태

DeFi 프로토콜에서 AML/KYC 구현이 가능한가? 그리고 이를 의무화 할 수 있는가?

기술 구현 자체는 여러가지 논의되고 있으나 탈중앙화 프로토콜 특성상 현실성, 실현 가능성 떨어짐

  • 컨트랙트는 불변성을 가지고 있어서 이미 attack vector에 따른 해킹 위험이 큰데 KYC/AML 준수 기능을 넣으면 외부 데이터를 참조하는 과정에서 새로운 attack vector가 생길 위험이 있다. → 더 큰 금전 손해를 야기
  • 모든 DeFi 프로토콜을 장악할 수 있는 것이 아니기 때문에 compliant service가 아닌 permissionless나 오픈소스 서비스로 이동할 수 있다(포크로 회피 쉬움) → 되려 사용자들의 규제 회피를 야기

*위 근거 2개는 아래 DeFi Self-Regulation 인용입니다

DeFi Self-Regulation: A Proposal for the Industry (INATBA Report, SEC-hosted PDF)에서는 DeFi에 기존 TradFi의 AML/KYC 규제를 도입하기는 어렵다며 AML/KYC에 대한 의무를 DeFi protocol 자체가 아닌 CASP가 갖는 것이 맞다고 주장

실제로 CASP는 On/Off-ramp 역할을 하고 이는 강한 규제를 받는 추세

https://www.linkedin.com/posts/juan-ignacio-amor-35ba2220_crypto-offramp-aml-activity-7386624777681244160-3W1o/

https://www.linkedin.com/posts/juan-ignacio-amor-35ba2220_crypto-offramp-aml-activity-7386624777681244160-3W1o/

Off-ramp에 대한 regulation이 near-bank-level만큼 엄격해지고 있음 → Source of Funds에 대한 증명을 명확히 해야함 → 현금화 단계에서의 규제 준수가 의무