일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Best of the Best
- 자살론
- 철학
- 코드엔진 베이직
- malware
- 논문리뷰
- h4ckinggame
- codeengn basic rce 01
- 사회적 사실
- 코드엔진 basic 5
- BoB 12기 최종합격 후기
- 에밀 뒤르켐
- bob
- 코드엔진
- BoB 12기
- 사회분업론
- 디지털 포렌식 트랙
- CodeEngn Basic 01
- CodeEngn
- CodeEngn Basic 5
- 리버싱
- Today
- Total
목록IT/DreamHack (8)
woonadz :)
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/cha9qU/btsGus2dtvY/qKqTtyoftgi07q6Ghnszp0/img.png)
SERIAL을 구하는 문제입니다. DA로 열었을 때, mfc로 GUI를 구현한 프로그램인 것을 확인할 수 있습니다. 이때 사용자 입력값을 찾아가는 방법은 여러가지가 있을 수 있지만 저는 두가지 방법으로 따라가보았습니다. 사용자 입력값과 관련되어 호출되는 문자열을 따라간다. Event ID를 이용하여 사용자 입력값을 검증하는 함수를 따라간다. 2번 방법은 인터넷에서 mfc를 분석할 수 있는 재미있는 방법인 것 같아 해당 예제로 공부해보았습니다. 좀 예전에 풀었던 문제인데 2번 분석을 해보고 싶어 다시 쓰게된 라업이라… 어떻게 풀었는지 잘 기억이 안납니다..ㅎㅎ 주석을 달아두었던 ida 파일도 삭제한 상태여서 처참히 코드만 남았습니다… (라업을 바로바로 작성해야하는 이유) 2번과 관련된 방법은 아래 링크를 ..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/lUrG8/btsGizVF7mR/6AxQL3EwuCD5H4lOBB3Kb1/img.png)
sub_160A의 반환값이 1이 되는 조건을 찾아야 합니다. sub_1395, sub_11D6, sub_14B6 함수의 반환값이 모두 1이 되는 조건을 찾아야 합니다. 사용자 입력값의 길이가 43 입니다. 위 로직을 통해 input 값의 형태가 DH{00000000-0000000000-0000000000-00000000} 이라는 것을 알 수 있습니다. calculate_string 함수를 통해 input 값에 대한 연산을 진행하고 반환값을 v4, v3, v2, v1 변수에 할당합니다. 각 문자에 대해 ASCII를 16진수로 변환해주는 연산을 수행하고 그 값을 v5 변수에 더하여 반환합니다. 위 함수들의 연산을 통해 calculate_string 함수의 반환값인 v1, v2, v3, v4의 값을 방정식으로..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/boJZs1/btsGeyWv8hW/cXYRckl05lAjWIHaAanhk0/img.png)
덤프된 환경이 아닌 실시간 환경이므로 비휘발성 데이터 수집을 통해 풀이 “로그인 할 때 마다 네트워크 데이터에 민감한 로그인 정보가 유출” ⇒ 로그온 관련 아티팩트 수집 crontab, /var/run, /etc/service, /etc/init.d 등의 스케줄링 관련 아티팩트 X 로그인 시에 발생하는 네트워크 패킷 분석 tcpdump를 뜨면 특정 경로로 불필요한 패킷이 너무 많이 보였습니다. 침해 PC 경로에서 시작하고, 175.117.153.116으로 도착하지 않도록 필터링을 걸어 확인해주었습니다. 다른 터미널에서 로그인을 했을 때 발생하는 패킷을 보면, 123.45.67.89의 경로로 사용자의 로그인 비밀번호가 전송되는 것을 확인할 수 있습니다. 처음에는 root 내의 모든 폴더를 대상으로 키워드 ..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bmtRWC/btsFQfPNO10/7HgoZExLEzPI1j32SLFkRk/img.png)
사실 문제 자체는 procmon, malware defense 등의 동적 분석 도구나 동적 디버깅을 통해 쉽게 해결할 수 있지만 코드의 로직을 좀 더 자세히 알아보기 위해 코드 정적 분석을 기반으로 풀이를 작성하였습니다. Cabinet 파일 바탕으로 만들어진 실행파일인 것을 확인할 수 있습니다. 이를 통해 기존 실행 로직에 또 다른 파일이나 폴더가 숨겨져 있을 것이라 추측할 수 있습니다. sub_140004754 함수가 주로 프로그램의 메인 로직을 담당합니다. sub_140004754 함수에서 호출하는 sub_14000526C 함수는 tmp 폴더 내에 폴더를 생성하는 함수입니다. 코드 동적 분석을 통해 생성되는 폴더의 이름과 경로를 확인하였습니다. sub_140004754 함수에서 호출하는 StartAd..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/lbmJF/btsFGCEph8C/IPbkeH73EQ2UZVIVw5qWyK/img.png)
sub_140001000 함수에 사용자 입력값을 인자값으로 주어서 인증 검사를 수행하는 것을 알 수 있습니다. _BOOL8 __fastcall sub_140001000(const char *input) { int i; // [rsp+20h] [rbp-18h] int v3; // [rsp+24h] [rbp-14h] v3 = strlen(input); if ( (v3 + 1) % 8 ) return 0i64; for ( i = 0; i < v3 + 1; i += 8 ) sub_1400010A0(&input[i]); return memcmp(input, &unk_140004000, 0x19ui64) == 0; } 비교 메모리(&unk_140004000) : '0x7E', '0x7D', '0x9A', '0x8B..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/spfrE/btr9GgHF7Xg/gZteh2L6Ya0EcruCRYrRc0/img.png)
DreamHack의 basic reversing 시리즈는 전체적인 로직은 같고, 입력값을 기반으로 serial과 비교하는 부분의 로직이 다르기 때문에 그 부분부터 설명한다. 문자열 참조를 통해 Input 값을 받아 serial 일치 여부를 판단하는 함수가 있는 곳으로 이동했다. rsp 값을 옮긴 rax 레지스터의 값과 18을 비교하는 것으로 보아 serial은 24자리라는 것을 추측할 수 있다. 사용자 입력값을 eax 레지스터에 옮긴다. 16진수 기준으로 0부터 17까지 증가하는 rsp 레지스터의 값을 ecx 레지스터에 옮기고 +1 을 한다. 사용자의 다음 입력값을 ECX 레지스터로 옮긴다. 사용자의 입력값을 더한다. (abcdefg라면 a+b, b+c, c+d 순) 특정 주소에서 값을 가져와 그 값을 ..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/dQZxmV/btr8ibNfBVF/QzyZ8P8BYCxAt3Kcy7fOKk/img.png)
DreamHack의 basic reversing 시리즈는 전체적인 로직은 같고, 입력값을 기반으로 serial과 비교하는 부분의 로직이 다르기 때문에 그 부분부터 설명한다. 1C와 비교하는 것으로 보아 총 28자리의 serial인 것을 추측할 수 있다. sar 명령어는 오늘 처음 보았다. sar : 오른쪽으로 밀어 낮은 bit를 내보내고 Carry Flag로 복사, 높은 bit 쪽에 0을 더하여 채운다. But keep sign(1) 해야한다. 사용자가 입력한 첫 값에 대해 위와 같이 계산한다. shl : 왼쪽으로 밀어(shift) 높은 bit를 내보내고 Carry Flag로 복사 낮은 bit쪽에 0을 더하여 채운다. 사용자가 입력한 첫 값에 대해 위와 같이 계산한다. shl 연산을 한 값과 F0을 an..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/ck27Tc/btrQMxHMhad/jpm01wSbStyqqGDQDOkToK/img.png)
문제 from Crypto.Util.number import bytes_to_long, getPrime flag = bytes_to_long(b'DH{???????????????????????????????????????????????????????}') p1 = getPrime(420) p2 = getPrime(420) p3 = getPrime(420) print(f'p1 = {p1}') print(f'p2 = {p2}') print(f'p3 = {p3}') print(f'c1 = {flag % p1}') print(f'c2 = {flag % p2}') print(f'c3 = {flag % p3}') output p1 = 152720747024314397374153010591098602427164998..