15번째로 푼 문제이다.

SQL Injection 문제인데... 내가 가장 자신있기도하지만
풀기는 귀찮아서 풀기 시작하기가 조금 꺼려지는 문제이기도 하다..!

문제이름은 외로운 사나이
lonely guys이다.



(lonely guys)



아래는 문제 페이지다.
문제 이름과 어울리게 외로운 남자들의 이름이 적혀있다.



(문제 페이지)



당연히 소스코드가 주어졌으니 소스코드를 보고 우리가 공략할 수 있는 부분을 확인해보자.



(소스 코드)



소스코드를 보니 select 문을 이용할 수 있는데
ordey by 뒤에 붙일 수 있다.. (몰랐지만 이게 조금 검색을 하게 만들었던 부분이다.)

order by reg_date 뒤에는 일반적으로 asc desc 가 오거나 혹은
order by reg_date, [컬럼명], 컬럼명 ... 등등 이렇게 올수 있다.

나는 콤마로 붙여 여러게를 있는 방법을 사용했다.
if 분기문을 사용해 Blind injection을 할 것이다.

우리가 공략해야할 테이블 이름은 authkey이며 컬럼이름은 authkey이다. (코드에 나와있다.)

먼저 POST방식으로 sort를 전달해야하므로 post form 문을 만들어주자.



(form 문 제작)



기본적으로 내가 사용하려는 if 문으로 blind injection의 공격 가능성을 체크해본다.

if(1=1, sleep(2),2)
만약 공격이 된다면 슬립이 걸려 2초가 멈췄다 동작할 것이다.




(인젝션)





(실행결과)



실행결과 2초가 멈추는 것을 알 수 있었다.

즉 if문을 사용해 공격할 여지를 확인했다.

if(조건,참,거짓) -> 조건문에 내가 확인하고 싶은 쿼리를 사용할 것이고 참에는 sleep을 걸어줄 것이다.
헌데.! sleep은 시간이 좀 걸리니까 에러기반으로 전향했다.
참 부분에 에러를 유발 시킬 수 있는 문구를 넣는것이다. 
내가 자주 사용하는 에러 유발 문구 cot(0)을 사용할 것이다.
cot(0)은 무한대이므로 에러가 난다.

먼저 길이를 알아보자.!
길이를 알기위한 조건문
length((select authkey from authkey limit 0,1))=길이
사용한 쿼리문
,if(length((select authkey from authkey limit 0,1))=i,cot(0),0)
i를 30부터 45까지 돌려주었다. (30이상으로 참이 나왔고 45 이상으로 거짓이 나왔기 때문)



(길이 확인)




(실행결과)



실행 결과 flag길이는 40글자라는 것을 확인 할 수 있었다.

이제 본격적으로 blind injection에 들어간다. 40글자를 찾을 것이다.
사용한 쿼리
,if(ord(substr((select authkey from authkey limit i,1),1,1))=j,cot(0),0)



(authkey 찾기)



(실행결과)



실행결과 authkey를 찾았고 문제를 해결할 수 있었다.


'WarGame > 500 Project' 카테고리의 다른 글

(17/500) Lord of the BOF - gremlin  (0) 2017.05.05
(16/500) Wargame.kr - ip log table  (0) 2017.04.20
(14/500) Wargame.kr - strcmp  (0) 2017.04.16
(13/500) Wargame.kr - SimpleBoard  (0) 2017.04.16
(12/500) Wargame.kr - tmitter  (0) 2017.04.15



분기문 하기에 앞서 사칙연산을 정리해보겠다.

사칙연산하는 C코드의 어셈블리어는 어떻게 구성될까?



(C코드)




컴파일 후 확인해본다!




(어셈블 코드)



저번 글에서 만들었던 형태가 비슷하게 나오는 것을 확인 할 수 있다.

오늘은 분기문을 공부 할 것이다.
jmp는 해당 주소로 이동하는 것이다.

이것을 이용하면 조건문도 만들 수 있고 반복문도 만들 수 있다.
실제로 C코드에서 if와 switch는 jmp 명령어로 이루어져있고
어셈블 차원에서 보면 똑같다.

사용 형식은
jmp addr
이런식으로 써준다.

그렇다면 jmp로 무한루프를 만들어보겠다.




(무한루프 코드)



jmp 명령에 의해 _start로 돌아간다.
_start는 레이블 이름으로 주소값이다. 컴파일 전에 주소값을 우리는 모르니 레이블 이름을 달아주어 사용한다.
컴파일한다.



(컴파일)



컴파일 후 실행해보면



(실행 모습)



실행되는 모습이다.

그렇다면 C코드의 기본적인 if문을 어셈블러로 구현해보자!
먼저 C코드의 기본적인 if문 코드이다.



(if문 코드)




(실행모습)



여기서는 조건 분기를 사용한다. 위의 jmp는 무조건 분기로 다른 조건없이 바로 해당 주소로 넘어가지만 조건분기는 조금 다르다.

조건 분기
 - EFLAGS 레지스터를 참조해서 분기할지 말지를 결정한다.
조건 분기문을 쓰기전에 cmp를 해줘야 EFLAGS에 기록하고 이걸 보고 조건문기문이
동작한다.

 - cmp

조건분기 종류를 살펴보면
 - je (jmp equal) = jz
 - jne (jmp not equal) = jnz
 - jl (jmp less)
 - jg (jmp greater)
 - jnl
 - jng
 - jle
 - jge
 - ja (jmp above) 초과
 - jb (jmp below) 미만
 - jna
 - jnb
 ...

3. cmp : 비교명령어
 cmp vleft vright
 -> 두개의 값이 같은지 비교
- vleft 값과 vright 값의 차를 구한다.
- 그 결과에 따라서 EFLAGS 레지스터의 플래그를 조절한다.
cmp에서 사용하는 flg
- ZF, SF
1) vleft - vright의 결과가 0인 경우
 : ZF = 1, SF=0 -> 두 값이 같다고 판단
2) vleft - vright의 결과가 음수인 경우
 : ZF=0, SF=1 -> 오른쪽이 더 크다.
3) vleft - vright의 결과가 양수인 경우
 : ZF=0,SF=0
조건분기문 사용 직전에 cmp를 해줘야한다.

이를 이용해 기본적인 if C코드를 어셈블러 코드로 구현하면 아래와 같다.



(조건분기문 사용)




(실행결과)



실행 결과 잘 나오는 듯하다.
(하지면 이 코드에는 문제점이 있다.)

값을 5보다 작게 2로 설정하여 확인해보겠다.



(작은 값 입력)




(실행결과)



실행결과를 보니 2가 작음에도 크다고 출력되었다.

왜 이럴까??
원인은 바로 점프하지 않고도 그 아래에 출력해주는 명령문이 있기 때문에 아래 코드가 순차적으로 실행 되었던 것이다. 이것을 막아주기 위해서는 아래 처럼 추가해주면된다.



(추가 코드)




(실행결과)



실행한 결과 작을 때는 이제 출력되지 않는 우리가 원하던 C코드의 동작을 하게 되었다.

다르게 표현을 하자면 jmp문 하나로도 완성 가능하다.



(다른 표현)



C코드를 컴파일 한 내용과 비교해보겠다.
상수끼리 비교하면 컴파일러가 알아서 계산을 해놓아서...
변수를 따로 선언을 해주었다.



(C코드 수정)



컴파일 후 어셈블러를 확인해보면



(어셈블 코드)



우리가 만든 코드와 비슷하게 나온 것을 확인 할 수 있다.

그렇다면 실습으로 아래와 같은 코드를 어셈블 코드로 만들어보자!



(실습 코드)



실습 결과는 아래와 같이 만들 수 있다.



(실습 결과)



jmp 문에 대한 내용이었다.




14번째 푼 문제이다.!

문제이름은 strcmp!
strcmp의 취약점을 이용한 문제이다.



(strcmp 문제)



문제 페이지이다.




(문제 페이지)



패스워드를 입력 칸이 하나있고 체크 버튼이 있다.

소스코드를 확인해보겠다.



(소스코드)



소스코드를 보니 POST방식으로 값을 전달한 것이 password와 비교하여 같으면 flag를 보여준다.

이것은 strcmp 함수의 취약점을 이용했다.
구글에 strcmp 까지 입력하니까 취약점이 연관검색어로 나왔다.
으음..

확인해보니 입력해보니 입력 인자로 배열이 들어가면 0을 반환하게 되어있다. 혹은 버젼에 따라 NULL을 리턴하는데 0이든 NULL이든 우리 문제에서는 == 로 비교하기 때문에 참이 되게 된다.

즉 입력으로 배열을 넣어주면된다.
POST방식이므로 버프슈트로 값을 변조해서 보내줄 것이다.




(값 변조)



password[] 배열을 보내주었다.




(문제 해결)



Flag를 얻을 수 있었다. ! :)


'WarGame > 500 Project' 카테고리의 다른 글

(16/500) Wargame.kr - ip log table  (0) 2017.04.20
(15/500) Wargame.kr - lonely guys  (0) 2017.04.18
(13/500) Wargame.kr - SimpleBoard  (0) 2017.04.16
(12/500) Wargame.kr - tmitter  (0) 2017.04.15
(11/500) Wargame.kr - type confusion  (0) 2017.04.15



13번째로 푼 문제이다. :)
인젝션 문제이다.

문제 이름! SimpleBoard




(SimpleBoard)



문제 페이지이다.



(문제 페이지)



게시판 형식의 페이지이다.

소스코드를 확인 해보자!




(소스코드)



소스코드를 보니 완전한 소스코드가 아니라 클래스 부분만 따로 때어낸 코드를 주었다.

코드 안에서는 우리가 공략할 수 있는 쿼리문을 보여준다.
여기에 사용된 쿼리는 update와 select 쿼리가 사용되었다. update 쿼리는 조회수 정보를 저장할 때 사용되었고 select 쿼리는 게시글을 클릭하였을 때 게시물을 보여주기 위해 사용되었다.

그렇다면 이러한 쿼리들은 어떤 인자를 받아들여 쿼리를 실행할까?
게시글 아무거나 클릭해보았다.



(게시글 클릭)



클릭해보니 GET방식으로 idx를 넘겨주고 있다.

또 소스코드를 보면 idx를 통해 select를 하고 update를 한다.
정확히 GET으로 받은 idx를 사용하는지는 안나왔지만 클래스 코드를 보고 유추하자면 그렇다.

그렇다면 idx 변수에 injection을 담아 보내보자!
4 and 1 을 보내본다.



(4 and 1)



4번 글이 실행되었다.
이와 비교해서
4 and 0
을 Injection해보았다.




(4 and 0)



화면에 아무것도 나오지 않는다.
즉 이말은 4 and 0의 쿼리가 잘 전달되어 게시글을 가져오지 못했다는 것이다.

그렇다면 제일먼저 이 테이블의 컬럼수를 알아보기 위해
order by를 이용할 것이다.




(order by 1)



쿼리 에러

여기서 당황했지만 코드를 다시 잘 살펴보게 되는 계기가 되었다.




(소스코드)



여기서 idx값이 전달되면 쿼리가 2개가 실행되는데
update 쿼리를 잘보면 우리가 보낸 4 and 1 order by 1을 하게 되면 여기서 에러가 난다는 것을 알 수 있다. 즉 update 쿼리가 실행되지 않게 해야하는데 쿠키값으로 view를 관리하는 것을 볼 수 있다.
이 값에 봤다고 설정이 되있다면 update쿼리는 실행되지 않는다.

매번 쿠키를 설정해서 보내기 귀찮으므로 파이썬을 이용해 코드를 작성해보겠다.



(작성한 코드)



이 코드를 보면 4 or 1 order by 1 를 보낸다.



(결과)



결과를 보니 잘 나오는 듯했다.
하지만 잘나온것은 아니다 왜냐! 4번글이 출력되었기 때문에
정상적이라면 1번글이 나왔어야한다.

이유를 헤메다 보니 쿠키에 저장되는 값을 url 인코딩으로 해줘야한다.!
그렇기에 url 인코딩해서 보내주면



(url 인코딩 injection)



(실행결과)



실행 결과를 보면 1번 글이 출력된 것을 확인 할 수 있다.

이제 order by를 이용해 컬럼의 수를 찾아보겠다.



(order by 5 injection)




(쿼리 에러)



1,2,3 이렇게 늘려가다보니 5에서 에러가 났다.
컬럼의 수는 4개라는 것을 알 수 있었다.

이젠 4개의 컬럼이 맞는지 union select 를 이용해 확인해 보겠다.
원래 안에 글의 개수가 4개이므로 출력해줘야하는 글의 위치는 4 (0부터시작하므로)
limit 4,1 을 붙여주었다.




(확인 injection)




(실행결과)



실행결과를 보니 1,2,3,4 가 출력되는 것을 확인 할 수 있었다.

이제 테이블 이름을 알아야했다.
테이블 이름을 알기위해
select table_name,2,3,4 from information_schema.tables 를 이용할 것이다.



(테이블 이름 injection)



(실행결과)



실행 결과를 보니 CHARACTER_SETS이 나왔다.
나는 이게 지금 내가 검색하고 있는 테이블 이름인줄 착각했었다.. 하지만 여러 테이블 이름 중 하나였다.

즉 테이블 이름을 쭉 전부 검색해서 확인할 필요가 있었다.



(테이블 이름 injection)




(실행결과)



실행결과 쭉 보니 의심갈만한 테이블 이름이 있었다.
SimpleBoard 와 README 였다.

SimpleBoard을 살펴보니 우리가 문제 페이지에서 확인할 수 있는 페이지가 전부였다.

남은건 README!

하지만 컬럼 이름은 모르는데.. 컬럼이름을 찾을까 하다가
그래도 flag라는 컬럼이 있지 않겠어? 라는 심정으로 찍어봤는데



(flag injection)




(실행 결과)


flag가 정말 나왔다...
문제해결..!! :)


'WarGame > 500 Project' 카테고리의 다른 글

(15/500) Wargame.kr - lonely guys  (0) 2017.04.18
(14/500) Wargame.kr - strcmp  (0) 2017.04.16
(12/500) Wargame.kr - tmitter  (0) 2017.04.15
(11/500) Wargame.kr - type confusion  (0) 2017.04.15
(10/500) Wargame.kr - md5 password  (0) 2017.04.14


12번째로 푼 문제이다!

tmitter


(tmitter)



아래는 문제 페이지이다.


(문제 페이지)



문제 페이지 보니 로그인하는 버튼과 회원가입하는 버튼이 있다.

회원가입 페이지에 들어가서 이것저것 해보다가 소스코드를 보니 힌트가 있었다.



(힌트)



개인적으로 나에게 이 힌트가 매우 컸다.
이곳저곳 쑤시지 않고 여기만 공략하면 됬기에!! ㅎㅎ

admin 으로 회원가입을 하라는 말이다.
그렇다면 해보자!



(거부)



admin 계정이 이미 있다고 나온다.
역시..

그렇다면 분명 select 쿼리가 날라가서 db를 검색하여 자료가 있으면 이미 존재한다고 나오는거겠지??
라는 생각이 들었다.

흠 우선 admin' # 을 넣어 오류를 내보자!



(sql injection)



응??
' 앞에 역슬래쉬가 붙었다.
이 워게임 사이트 앞에서 php 코드를 살펴보니 그 injection 방지용으로 어떤 함수를 잘 쓰던데 그거 썻나보다. ' 앞에 이스케이프 된다.

그렇다면 널바이트는 어떻게 될까? 널바이트는 포스트로 전달 못하니
버프슈트를 이용해서 널바이트를 추가해서 보내보자!



(널바이트 삽입)



결과는...




(결과)



널바이트앞에도 이스케이프 문자가 붙는다.

역시..! 그 mysql_real_escape_string()을 쓰는거 같다.
아그러면 or나 이런거도 붙을텐데... 고민이 들었다.

일단 이 함수의 우회법은 안다.
바로 싱글 쿼터 앞에%bf를 넣어주면 %bf가 이스케이프 문자와 합쳐져서 싱글쿼터가 살아남는다.
그 뒤에 && 0 을 추가시켜주어 select 문에 아무것도 안나오게하고
그래서 회원가입이 되게 하는게 나의 전략이다.



(sql injection)



실행결과 회원가입이 되었다.!

정한 비밀번호로 로그인을 해보면




(로그인)



로그인이 되고 flag를 찾을 수 있다.!



(문제 해결)

'WarGame > 500 Project' 카테고리의 다른 글

(14/500) Wargame.kr - strcmp  (0) 2017.04.16
(13/500) Wargame.kr - SimpleBoard  (0) 2017.04.16
(11/500) Wargame.kr - type confusion  (0) 2017.04.15
(10/500) Wargame.kr - md5 password  (0) 2017.04.14
(9/500) Wargame.kr - md5_compare  (0) 2017.04.13



11번째로 푼 문제이다.

제목은 타입 혼란??
type confusion



(type confusion)



문제 페이지는 아래와 같다.



(문제 페이지)




체크박스 하나있고 소스코드를 볼 수 있는 링크가 있다.

소스코드를 살펴보겠다.




(소스코드 분석)



소스코드를 정리하자면
POST방식으로 json 변수에 값을 넣어 전달해야하고
그 값의 key값이 페이지 내 생성된 key값과 같으면 flag가 나온다.

여기서 key값은 임의로 생성되므로 알아낼 길이 없다.
다만 비교연산자를 == 로 쓰는것을 보아 이 취약점을 이용하면 풀릴거라는 생각이 들었다.

전에 비교연산자로 인해 며칠을 고민했던 터라 이번 문제는 쉽게 풀 수 있었다.

바로 ==로 비교할때 문자는 0으로 변환되기 때문에 숫자 0과 비교하면 참이 나온다.


(비교 참)



그렇다면 나는 key에 0을 넣어 json 인코딩해서 넣어주면 된다!



(json 인코딩)



그런데 POST라면서 보낼 폼이 없다... 저기 체크박스도 name이 다르게 설정되어 안된다..

그래서 내가 만들어서 보냈다.




(son 값 보내기 폼)



만든 폼을
관리자모드에서 적어주어 폼을 보내준다.



(폼 작성)





(보내기)



보내면 flag가 나오고 문제가 풀린다! :)



(문제 해결)


'WarGame > 500 Project' 카테고리의 다른 글

(13/500) Wargame.kr - SimpleBoard  (0) 2017.04.16
(12/500) Wargame.kr - tmitter  (0) 2017.04.15
(10/500) Wargame.kr - md5 password  (0) 2017.04.14
(9/500) Wargame.kr - md5_compare  (0) 2017.04.13
(8/500) Wargame.kr - fly me to the moon  (0) 2017.04.13


10번째 푼 문제이다! 

이름은 md5 password 이다.


(md5 password)



아래는 문제 페이지이다.




(문제 페이지)



비밀번호를 입력하는 칸이 하나 나온다.

소스코드를 보면 해시된 값을 넣어 테이블에서 select 검색을 한다.
그런데 조금 이상한 점이 있다.



(소스코드)



바로 md5 해시 함수에서 2번째 인자로 true를 주었다는 것이다.

기본적으로 디폴트 값은 default 이다.
이 값이 true로 넘어가게 되면 출력이 바이너리로 출력되게 된다. 근데 이게 바로 취약할 수 있다는 것이다. 해시 되는 과정에서 ' (싱글쿼터) 등 공격자가 필요한 특수문자를 만들어낼 수 있기 때문이다.

우리가 원하는 값은 '=' 이 값이 있으면 된다. 왜냐?
쿼리문장에서 where password='sdfds'='gfgfg' 
이런식으로 만들어주어 이렇게 되면 참으로 출력이되어 모든 값이 출력되기 때문이다.

예를들어 아래와 같이


(원하는 해시값)



우리가 원하는 해시값이다.

이렇게 나오는 저 값을 입력하게 되면 로그인이 되고 플래그가 나오게 된다.



(문제 해결)


'WarGame > 500 Project' 카테고리의 다른 글

(12/500) Wargame.kr - tmitter  (0) 2017.04.15
(11/500) Wargame.kr - type confusion  (0) 2017.04.15
(9/500) Wargame.kr - md5_compare  (0) 2017.04.13
(8/500) Wargame.kr - fly me to the moon  (0) 2017.04.13
(7/500) Wargame.kr - WTF_CODE  (0) 2017.04.12


오늘은 어셈블리로 사칙연산 명령어를 공부할 것이다.

1. 덧셈
명령어 : add
형식
add     dst,     src
:dst에 더한값을 저장한다.
dst에는 레지스터, 메모리가 올 수 있고
src에는 레지스터 메모리 상수가 올 수 있다.

*주의 한번에 두개의 메모리를 참조할 수 없다.
ex) add 메모리, 메모리
(이건 mov도, 기타등등 여러 명령어에서도 마찬가지이다.)

그러면 add명령어를 사용해보겠다.



(add 코드)



eax에 2를 저장하고 add 명령어를 이용해 3을 더했다.

실행하게되면


(실행화면)



결과는 5가 나온다.

이번에는 레지스터가 아닌 메모리를 사용해 덧셈을 해보겠다.



(메모리 사용)



sum 주소에 2를 저장하고 3을 더해주었다.
대신 주소값을 쓰는게 아니라 주소에 있는 데이터값을 쓰는것이므로 
[ ] 브라켓을 씌워준다.


(실행결과)



실행 결과 역시 5가 나왔다.

2. 뺄셈
명령어 : sub
형식
sub     dst,     src
내용은 덧셈과 같다.

그렇다면 뺄셈을 사용해보겠다.



(뺄셈 코드)



(실행화면)



실행화면을 보면 10-5의 결과로 5가 제대로 나온 것을 볼 수 있다.

* 실습 문제
 - 다음과 같은 두 개의 값의 덧셈 결과와 뺄셈 결과를 출력
segment  .data
 num1     dd     20
 num2     dd     10



(실습 코드)




코드를 보면 알겠지만 조금 오바해봤다.

실제 계산부분만 보면 되겠다.
실행해보면



(실행결과)




덧셈과 뺄셈이 잘 되는 걸 확인 할 수 있다.

이번에는 덧셈은 레지스터, 뺄셈은 (꾸이꾸이) 메모리를 사용해 해보겠다.



(실습 코드2)




(실행결과)



실행 결과가 같다.

이번에는 주소값과 주소에 있는 데이터와의 차이를 보겠다.

아래의 코드를 먼저 본다.



(어셈블 코드)



위에는 그냥 num 아래는 [num] 을 사용했다.
실행하여 결과를 확인해보자.



(실행결과)



실행 결과를 보니 그냥 num을 쓴 것은 주소값이 출력되었고
[num]은 그 주소에 있는 데이터 10의 값이 출력되었다.

여기서 이제 mov와 lea를 비교하면서 lea가 뭔지 살펴보겠다.
lea는 mov와 거의 비슷하다. 다만 조금 다른점이 있는데 직접 눈으로 확인해보겠다.

아래에 lea와 mov를 추가해서 확인해본다.



(mov와 lea 추가)




(실행결과)




실행 결과를 보니 mov로는 [num]이기 때문에 우리가 알던대로
num의 주소에 있는 데이터인 10이 출력되었다.

근데 이상한점이 있다. lea로 [num]을 넣어주었는데
주소값이 출력되었다.
바로 이게 차이점이다.
lea는 [ ] 브라켓을 꼭 써야하고
그 안에있는 값 그대로 출력해준다. 그래서 num의 주소값이 그대로 출력된 것이다.

바로 이 점을 이용해 덧셈을 할 수 있는데
아래 코드에서 마지막 부분을 보면 된다.



(lea를 통한 덧셈)




(실행 결과)



실행 결과를 보면 14로 덧셈이 잘 된것을 확인 할 수 있다.
lea eax, [ebx+4]
이렇게 하면 우리가 ebx에 10을 넣어주었으니 ebx는 10이되고 10+4로 14의 값이 그대로 전달되는 것이다.

3. 곱셈
명령어 : mul, imul
형식
mul     피연산자
-> 부호없는 곱셈

imul 피연산자
 imul 피연산자, 피연산자, 피연산자
 -> 최대 3개까지 올 수 있다.
 -> 부호 있는 곱셈

mul 는 a 레지스터를 쓰게 되어있다.
무조건 a레지스터에 있는 값과 곱하게 된다.

그렇다면 곱셈을 사용해보자!



(곱셈 코드)



(실행화면)



실행화면을 보면 곱셈의 결과 6이 나온 것을 확인할 수 있다.

이제 곱셈의 이상한?점을 볼 차례이다.
바로 사이즈가 커진다는 것인데
곱셈은 결과가 원래 사이즈를 넘어갈 수 가 있다.
그렇기 때문에 결과를 큰 사이즈에 저장하게된다.
위에서도 보다시피 1바이트 곱셈인데 결과는 우리가 eax를 푸쉬해서 출력했다.

아래처럼 255로 꽉채워서 곱셈을 하게되면 사이즈가 초과되기 때문에 결과는 eax로 저장이 된다.



(초과 곱셈)



(실행결과)



그렇기 때문에 곱셈의 결과가 정확하게 나올 수 있는 것이다.

그러면 이제 imul을 사용해보겠다. 이 명령어는 부호가 있는 곱셈이라고 했다.
부호가 있을때 사용하라는 말이 아니라 비트중 MSB를 인식한다는 뜻이다.

우리가 255 255 곱셈을 하게되면 어떻게 될까? 왜냐하면 MSB가 모두 1이기 때문에 궁금하다.



(imul)



(실행결과)



실행결과 255를 -1로 인식하여
-1 곱하기 -1 을 하여 1이 나왔다.

imul은 mul처럼 사용할 수 도 있지만
인자를 2개 3개까지 받을 수 있는데 살펴보겠다.

2개를 쓸 때



(2개 사용 코드)




(실행 모습)



2개를 쓸 때는 이렇게 사용한다.

3개를 쓸 때는?



(3개 사용)




(결과)



2번째 3번째 곱셈의 결과를 1번째 인자에 저장한다.

곱셈은 결과가 사이즈가 초과할 수 있어 그보다 더 큰 레지스터에 저장한다고 했다.
그렇다면 eax 4바이트 단위의 곱셈은 어디다 저장이 되는 걸까?

해보자!



(초과 결과 코드)



(실행 모습)



eax를 출력해보니 뭔가 완전하지 않은듯한 느낌이든다.

원래 곱셈의 결과라면
0x11111111  *  0x22222222 는 아래와 같다.



(결과)



그렇다면 앞 부분은 어디갔다는 말인가?!

바로 edx에 저장된다.
edx도 함께 출력해보겠다.



(edx 추가 출력)




(실행화면)



실행화면을 보면 eax와 edx에 나누어서 결과가 저장이 된 것을 확인 할 수 있다.

나머지와 mod 연산은 다음 글에서 이어서 써보겠다. :)




9번째 푼 문제이다.

이 문제는 MD5 해쉬 충돌문제인 줄 알았지만 비교연산자의 취약점을 말하고 있던 문제였다.

md5_compare 문제이다!


(md5_compare 문제)



아래는 문제 페이지다.



(문제 페이지)



문제 페이지를 보면 입력값 2개가 보이고 chk 버튼이 보인다.

그러면 소스코드를 확인해보겠다.



(소스코드)



소스코드를 내가 나름 주석으로 분석했다.

결론적으로 v1입력에는 알파벳만
v2입력에는 숫자만 입력하여 md5가 같아야 된다는 것이다.

여기서 완전히 같은 값을 찾기는 힘드므로 == 비교연산자의 취약점을 이용해보도록 하자

== 비교연산자는 타입을 보지 않는다.
그리고 문자열에 숫자가 있다면 == 비교할 때 숫자로 인식하여 비교한다.

나는 e -> 지수표현을 이용할 것이다. 0e어쩌구~ 이렇게 나오면 0으로 인식한다는 것이다.
그러니! 숫자만 넣었을때 앞 두자리가 0e 영어만 넣었을때 앞 두자리가 0e면 된다는 것이다.

(숫자 입력)




숫자 해쉬 시 앞에 0e로 시작하니 이 값은 == 비교할 때 0이 될것이다. 또

(알파벳)




알파벳입력시
앞에 0e 이므로 == 연산시 0으로 취급될 것이다.

즉 두 값은 같다고 결과가 나올 것이고! flag를 ??

해보자!




(입력)



(결과)



문제 해결!


'WarGame > 500 Project' 카테고리의 다른 글

(11/500) Wargame.kr - type confusion  (0) 2017.04.15
(10/500) Wargame.kr - md5 password  (0) 2017.04.14
(8/500) Wargame.kr - fly me to the moon  (0) 2017.04.13
(7/500) Wargame.kr - WTF_CODE  (0) 2017.04.12
(6/500) Wargame.kr - flee button  (0) 2017.04.11


8번째 푼 문제이다.

이번 문제 푸느라 눈 빠지는 줄 알았다...
(내가 잘 몰라서 그런거일수있지만..)

8번째 풀이 문제! fly me to the moon



(문제)



아래는 문제 페이지다.



(문제 페이지)



문제 페이지에 들어가면 게임을 하게된다.

그런데 벽이 점점 좁아지면서 깰수 없는... 지경에 이른다. 게다가 점수는 31@@@@ 엄청 많이 이상 받아야 된다고 나온다..

자바스크립트 우회문제구나! 하고 들어가보니.!



(스크립트)



역시! 스크립트는 곱게 줄리 없지!

뷰티하게 정렬해주자.



(스크립트 코드)



이제 좀 사람이 볼만해졌다.

이 코드를 분석하느라 오래걸렸다.. 실은 완벽하게 분석하려다 포기하고
게임에 핵심되는 부분만 골라서 봤다.

내가 원했던 것은 벽에 부딛혀도 안죽게하기!
그런 함수를 뒤지다보니 죽는 함수가 나오는 곳을 발견하였다.



(죽는 함수)



이 조건을보면 벽에 부딛히는 조건을 적어놨다.
나는 요 || (or)연산자를 && (and) 연산자로 바꾸어 죽지 않게 했다.
근데... 난독화되어있는 코드라..
다행이도 || 는 한번쓰인거라서 찾아서 &&로 바꾸어 주기만 하면 됬다.



(|| 사용된곳)



바로 이곳을 && 로 수정해서 다시 스크립트를 입력해주었다.

그랬더니 벽에 아무리 부딛혀도 무적의 전투기가 되었다.



(무적의 전투기)



그런데 또 한가지 문제가 생겼다. 점수가 목표치 31@@@@@ 어쩌구 까지 가는데 오래걸린다...

그래서 점수와 관련된 함수가 이용되는 곳을 공략했다.



(점수가 올라가는 조건)



바로 이 게임에서는 c_s 등 여러 시간에 관련된 시간 변수를 두어 여러가지 동작을 일으켰는데
c_s는 20에 한번씩 0으로 리셋되어 점점 1씩 올라간다. 바로 0으로 리셋될때 점수가 올라가는데
여기서 c_s >20 조건을 c_s>=0 으로 주어 점수가 파파팍 올라가게 했다.

여기서 점수가 하나씩 올라가는 것에 불만을 품고 점수를 한번에 더더 많이 올리기 위해 점수 올리는 함수를 추적하였다.




(점수 상승함수)




(점수 상승함수)



이 곳에 ++로 1씩 증가하게 되어있었는데
이 ++을 여러번 복사 붙여넣기하여 한번에 점수가 1씩이 아닌 팍팍 올라가게 했다.


(점수 팍팍 코드)




이렇게 세팅하고 시작하니 무적의 전투기가 점수가 파파팍 쌓이는 것을 볼 수 있다.



(무적전투기 죽이기)



이렇게 계속 냅둬도 내 전투기는 무적이라 안죽는다.. 그래서 게임이 안끝나는데
내가 죽이는 함수를 이용하여 죽여줘야한다.

31@@@@@ 이상이 될때 전투기를 죽여주면
키가 나온다~!


(문제 해결)


'WarGame > 500 Project' 카테고리의 다른 글

(10/500) Wargame.kr - md5 password  (0) 2017.04.14
(9/500) Wargame.kr - md5_compare  (0) 2017.04.13
(7/500) Wargame.kr - WTF_CODE  (0) 2017.04.12
(6/500) Wargame.kr - flee button  (0) 2017.04.11
(5/500) Wargame.kr - QR Code Puzzle  (0) 2017.04.11

+ Recent posts