#About


L_01

Q : 지성이는 홈쇼핑을 하다 이상한 페이지에 접속하여 악성코드에 감염되었다! 악성 스크립트에 포함되어 있는 쉘코드를 다운로드 하는 URL을 찾아라!


Q : J.S Park was surfing a home shopping site and got infected by malware code! Find out the URL that the shellcode(contained in the malware script) attempts to download content from.


# -*- coding:utf-8 -*-

import socket
import dpkt

def extract(pcap):
for ts,buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
# http_req = dpkt.http.Request(tcp.data)
# if http_req.uri.find('<script>') >=0:
# print http_req.uri
if buf.find("<script>") != -1:
print "[+] 출발지 : "+src+"도착지 : "+dst
print buf
# print buf[buf.find("<script>"):buf.find("</script>")+1],
except:
pass

def main():
p = open('C:/2011_HTP_PreQual_PROB.pcap','rb')
pcap = dpkt.pcap.Reader(p)
extract(pcap)

if __name__=='__main__':
main()


주어진 문제에서 키워드는 악성 스크립트이기에 find 명령을 이용하여 <script>로 시작하는 값이 있으면 출력하도록 만든 것이며 


주석의 내용은 임의로 작성해본 코드라 이 코드를 보고 있는 분께서는 생각안하셔도 되는 부분임.


[그림 1] - 악성 스크립트로 추정되는 스크립트 확인


출력결과를 확인하다 보면 <script>가 아닌 <SCRIPT>로 시작하여 의심을 사기에 충분한 스크립트가 확인되며 


자세한 결과를 확인하기 위해 출발지와 도착지 아이피를 기준으로 아래와 같이 패킷을 확인해보았다


[그림 2] - 필터링을 통한 패킷 확인


패킷 번호 6568번에서 [그림 1]에서 찾았던 페이로드를 확인할 수 있었으며 TCP stream을 통해 아래와 같이 페이로드를 확인할 수 있었다


[그림 3] - 페이로드 확인


페이로드가 유니코드로 되어 있음을 확인 후 온라인 컨버팅을 제공하는 사이트에서 hex 값을 아래와 같이 추출해 낼 수 있었다



[그림 3] - 헥스 값 확인


.... 나중에 이어 씀



'Wargame' 카테고리의 다른 글

2013 [Hack The Packet] L_01  (0) 2018.03.21
2011 [Hack The Packet] L_03  (0) 2018.03.21
[FEDORA CORE 4] Dark_stone > Cruel  (0) 2017.12.29
[MEMORY] 2012 Nuit Du hack > Password Manager 2  (0) 2017.12.28
[MEMORY] 2012 Nuit Du Hack > Password Manager 1  (0) 2017.12.28


#About


기부를 하고 싶은 마음은 있으나 금전적으로 여유가 되지 못해 기부를 못하는 사람들을 위해서 카카오라는 기업에서는 

도움이 필요한 사람들을 대상으로 카카오 사용자의 "응원"과 "공유" 1건당 사용자 대신 100~200원 가량의 기부금을 내준다.


오랜 친구로부터 이 사실을 알게 된 후, 나 또한 기부를 하고 싶은 마음은 있었으나 금전적 여유가 되질 못해 하지 못했기에,

이 기회를 통해 파이썬 자동화 스크립트 제작을 통해  게시물 마다 "응원합니다"라는 작은 댓글을 다는 프로그램을 만들기로 마음 먹었다.




#Scripts interpretation




# -*- coding:utf-8 -*-
import urllib2
from bs4 import *
from selenium import webdriver

# Open Chrome Driver
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(1)
driver.get("https://together.kakao.com/fundraisings/now")

# Auto Login Function
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath('//*[@id="email"]').send_keys('카카오톡 이메일 주소를 입력하세요')
driver.find_element_by_xpath('//*[@id="password"]').send_keys('카카오톡 이메일 주소의 비밀번호를 입력하세요')
driver.find_element_by_xpath('//*[@id="btn_login"]').click()

# See More Details
for i in range(5):
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

for j in range(1,115):
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath('//*[@id="txtCmt"]').send_keys(u'응원합니다')
driver.find_element_by_xpath('//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
driver.back()

# Full URL (containing href)
# give = list()

# Find Href Value
# html = driver.page_source
# soup = BeautifulSoup(html,'html.parser')
# item = soup.find('ul',{'class':'list_fund fund_raising'})
# for li in item.findAll('li',{'class':'listcard'}):
# for href in li.findAll('a',href=True):
# give.append("http://together.kakao.com"+href['href'])


1차 미완성 본이며 댓글을 작성하는 동작만 가능하다


# -*- coding:utf-8 -*-
import time
import urllib2
from bs4 import *
from selenium import webdriver

'''
Author : Loddy
Date : 2018-02-21 (UTC + 09 : 00)
Nationality : Republic Of Korea
Purpose : Auto Give Program
'''

# Extract Title
def title_extract():
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
for title in soup.find('title'):
print u"[+] 기부 완료 : {}".format(title)

def give_money():
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
money = soup.select('#mArticle > div.my_cover > div > div.info_append > dl > dd:nth-child(4)')
for don in money:
print don.text

# Open Chrome Driver
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(1)
driver.get("https://together.kakao.com/fundraisings/now")

# Kakao Login
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath('//*[@id="email"]').send_keys('카카오 이메일을 입력하세요')
driver.find_element_by_xpath('//*[@id="password"]').send_keys('카카오 이메일의 비밀번호를 입력하세요')
driver.find_element_by_xpath('//*[@id="btn_login"]').click()

# See More Details ( 게시물 더보기 )
for i in range(5):
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

# For Counting How many I gived
for j in range(1,3):
try :
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath('//*[@id="txtCmt"]').send_keys(u'응원할게요')
driver.find_element_by_xpath('//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
title_extract()
driver.back()
driver.find_element_by_xpath('//*[@id="toast-container"]/div[2]/div/div[2]/div').click()
except : pass

driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/button[1]').click()
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/div/a[2]').click()
give_money()

2차 수정본


만들당시는 됐는데 현재 2018-03-24는 스크립트가 돌아가질 않아서 다시 수정해서 업로드할 예정




# -*- coding:utf-8 -*-
import urllib2
from bs4 import *
from selenium import webdriver

'''
Author : Loddy
Date : 2018-02-21 (UTC + 09 : 00)
Nationality : Republic Of Korea
Purpose : Auto Give Program
'''

# Extract Title
def title():
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
for title in soup.find('title'):
print u"[+] 기부 완료 : {}".format(title)
item = soup.find('dl', {'class': 'detail_fund fund_belong'})
for person in item.find('dt', {'class': 'tit_fund'}):
for total in item.find('dd', {'class': 'txt_fund'}):
persons = int(person[person.find('(') + 1:person.find(')') - 1].replace(',','')) # 응원기부 (xxx명)
totals = int(total.replace(u'원', '').replace(',', '')) # xx,xxx원
print u"\t[-] 기부 금액은 {}원 입니다".format(totals / persons)

# Open Chrome Driver
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(1)
driver.get("https://together.kakao.com/fundraisings/now")

# Kakao Login
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath('//*[@id="loginEmail"]').send_keys('카카오 이메일을 입력하세요')
driver.find_element_by_xpath('//*[@id="loginPw"]').send_keys('카카오 이메일의 비밀번호를 입력하세요')
driver.find_element_by_xpath('//*[@id="login-form"]/fieldset/button').click()

# See More Details ( 게시물 더보기 )
for i in range(5):
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

# For Counting How many I gived
for j in range(1,3):
try :
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath('//*[@id="txtCmt"]').send_keys(u'응원할게요')
driver.find_element_by_xpath('//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
title()
driver.back()
driver.find_element_by_xpath('//*[@id="toast-container"]/div[2]/div/div[2]/div').click()
except :
pass

# driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/button[1]').click()
# driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/div/a[2]').click()

3차 수정본

2018-04-29 21:42


# -*- coding:utf-8 -*-
import urllib2
from bs4 import *
from selenium import webdriver
import pymysql

'''
Author : Loddy
Date : 2018-02-21 (UTC + 09 : 00)
Nationality : Republic Of Korea
Purpose : Auto Give Program
'''

conn = pymysql.connect(host='localhost',user='root',password='apmsetup', db='give',charset='utf8mb4')
curs = conn.cursor()
table = '''
CREATE TABLE information(
idx int(5) not null auto_increment,
title varchar(64) not null,
money varchar(16) not null,
primary key(idx));
'''
curs.execute(table)

data = tuple()

# Extract Title
def extract_title_and_money():
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
for title in soup.find('title'):
print u"[+] 기부 완료 : {}".format(title)
item = soup.find('dl', {'class': 'detail_fund fund_belong'})
for person in item.find('dt', {'class': 'tit_fund'}):
for total in item.find('dd', {'class': 'txt_fund'}):
persons = int(person[person.find('(') + 1:person.find(')') - 1].replace(',','')) # 응원기부 (xxx명)
totals = int(total.replace(u'원', '').replace(',', '')) # xx,xxx원
print u"\t[-] 기부 금액은 {}원 입니다".format(totals/persons)

# Open Chrome Driver
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(1)
driver.get("https://together.kakao.com/fundraisings/now")

# Kakao Login
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath('//*[@id="loginEmail"]').send_keys('카카오 이메일을 입력해주세요')
driver.find_element_by_xpath('//*[@id="loginPw"]').send_keys('카카오 이메일의 비밀번호를 입력해주세요')
driver.find_element_by_xpath('//*[@id="login-form"]/fieldset/button').click()

# See More Details ( 게시물 더보기 )
for i in range(5):
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

# For Counting How many I gived
for j in range(1,4):
try :
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath('//*[@id="txtCmt"]').send_keys(u'응원할게요')
driver.find_element_by_xpath('//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
extract_title_and_money()
# sql = "INSERT INTO information(idx,title,money) values({},{},{})".format(j)
driver.back()
driver.find_element_by_xpath('//*[@id="toast-container"]/div[2]/div/div[2]/div').click()
except :
pass

driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/button[1]/img').click()
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/div/a[2]/span').click()

4차 수정본 ( 데이터베이스 연계과정을 시도 )


# -*- coding:utf-8 -*-
import urllib2
from bs4 import *
from selenium import webdriver
import pymysql
import xlsxwriter as xlsx
'''
Author : Loddy
Date : 2018-02-21 (UTC + 09 : 00)
Nationality : Republic Of Korea
Purpose : Auto Give Program
'''

# conn = pymysql.connect(host='localhost',user='root',password='apmsetup', db='give',charset='utf8mb4')
# curs = conn.cursor()
# table = '''
# CREATE TABLE give_list(
# idx int(5) not null auto_increment,
# title varchar(256) not null,
# money varchar(10) not null,
# primary key(idx));
# '''
# curs.execute(table)

# Extract Title
def extract_title_and_money():
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
for title in soup.find('title'):
print u"[+] 기부 완료 : {}".format(title)
item = soup.find('dl', {'class': 'detail_fund fund_belong'})
for person in item.find('dt', {'class': 'tit_fund'}):
for total in item.find('dd', {'class': 'txt_fund'}):
persons = int(person[person.find('(') + 1:person.find(')') - 1].replace(',','')) # 응원기부 (xxx명)
totals = int(total.replace(u'원', '').replace(',', '')) # xx,xxx원
print u"\t[-] 기부 금액은 {}원 입니다".format(totals/persons)

# Open Chrome Driver
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(1)
driver.get("https://together.kakao.com/fundraisings/now")

# Kakao Login
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath('//*[@id="loginEmail"]').send_keys('')
driver.find_element_by_xpath('//*[@id="loginPw"]').send_keys('')
driver.find_element_by_xpath('//*[@id="login-form"]/fieldset/button').click()

# See More Details ( 게시물 더보기 )
for i in range(5):
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

# For Counting How many I gived
for j in range(1,4):
try :
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath('//*[@id="txtCmt"]').send_keys(u'응원할게요')
driver.find_element_by_xpath('//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
extract_title_and_money()
driver.back()
driver.find_element_by_xpath('//*[@id="toast-container"]/div[2]/div/div[2]/div').click()
except :
pass
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/button[1]/img').click()
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/div/a[2]/span').click()ㅇ

5차 수정본 ( 데이터베이스 연계 과정에 실패 )


# -*- coding:utf-8 -*-
from bs4 import *
from selenium import webdriver
import xlsxwriter as xlsx

'''
Author : Loddy
Date : 2018-04-29 23:36 (UTC + 09:00)
Nationality : Republic of Korea
Purpose : Automative Give
'''

# 엑셀 파일 생성
wb=xlsx.Workbook("C:/Users/HighTech/Desktop/result.xlsx")
ws=wb.add_worksheet()

# 엑셀 셀 속성 설정
format0=wb.add_format({'border':2,'bold':True,'align':'center','fg_color':'white','font_color':'black'})
format1=wb.add_format({'border':1,'bold':True,'align':'center','fg_color':'white','font_color':'black'})

# 엑셀 셀 너비 설정
ws.set_column('A:A',10)
ws.set_column('B:B',100)
ws.set_column('C:C',10)

# (x+1,y+1)의 위치에 데이터 입력 및 셀 속성 설정
ws.write(0,0,u'번호',format0)
ws.write(0,1,u'제목',format0)
ws.write(0,2,u'금액',format0)

# 엑셀 행을 바꾸기 위한 변수 init 할당
global init
init = 1

def write(count):
ws.write(init,6,count)
ws.write(init,7,name)
ws.write(init,8,don)
init +=1

# 기부 컨텐츠 제목 및 기부 금액을 담을 리스트 할당
name = list()
don = list()

# 기부 컨텐츠 제목 및 기부 금액 추출
def extract_title_and_money():
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
for title in soup.find('title'):
name.append(title)
print u"[+] 기부 완료 : {}".format(title)
item = soup.find('dl', {'class': 'detail_fund fund_belong'})
for person in item.find('dt', {'class': 'tit_fund'}):
for total in item.find('dd', {'class': 'txt_fund'}):
persons = int(person[person.find('(') + 1:person.find(')') - 1].replace(',','')) # 응원기부 (xxx명)
totals = int(total.replace(u'원', '').replace(',', '')) # xx,xxx원
don.append(totals/persons)
print u"\t[-] 기부 금액은 {}원 입니다".format(totals/persons)

# 크롬 웹 드라이버를 이용한 다함께 카카오 페이지 오픈
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(1)
driver.get("https://together.kakao.com/fundraisings/now")

# 다함께 카카오 로그인 기능
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath('//*[@id="loginEmail"]').send_keys('카카오 이메일을 입력하세요')
driver.find_element_by_xpath('//*[@id="loginPw"]').send_keys('카카오 이메일의 비밀번호를 입력하세요')
driver.find_element_by_xpath('//*[@id="login-form"]/fieldset/button').click()

# 한 번에 볼 수 있는 게시물이 20개 이므로, 전체 게시물 보기 클릭.
# for i in range(7):
# driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

# 실제 기부 과정을 작동시키는 중심 코드
for j in range(1,141):
try :
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath('//*[@id="txtCmt"]').send_keys(u'응원할게요')
driver.find_element_by_xpath('//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
extract_title_and_money()
ws.write(init,0,j,format1)
ws.write(init,1,name[j-1],format1)
ws.write(init,2,don[j-1],format1)
init+=1
driver.back()
driver.find_element_by_xpath('//*[@id="toast-container"]/div[2]/div/div[2]/div').click()
if j%20==0:
driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()
except :
pass
wb.close()

print "[+] 총 기부 횟수 = {}회".format(len(name))
print "[+] 총 기부 금액 = {}원".format(sum(don))

6차 최종 완성


데이터베이스 아닌 엑셀 연계를 통한 결과 값 추출 스크립트.


for j in range(1,141)에서 141(141-1)은 최대 게시물 수를 의미하며 해당 사이트에서 유동적으로 변하므로 유의 바랍니다


# -*- coding:utf-8 -*-
from bs4 import *
from selenium import webdriver
import xlsxwriter as xlsx

'''
Author : Loddy
Date : 2018-04-30 22:17 (UTC + 09:00)
Nationality : Republic of Korea
Purpose : Automative Give
'''

# 엑셀 파일 생성
wb=xlsx.Workbook("C:/Users/HighTech/Desktop/result.xlsx")
ws=wb.add_worksheet()

# 엑셀 셀 속성 설정
format0=wb.add_format({'border':2,'bold':True,'align':'center','fg_color':'white','font_color':'black'})
format1=wb.add_format({
'border':1,'bold':True,'align':'center','fg_color':'white','font_color':'black'})

# 엑셀 셀 너비 설정
ws.set_column('A:A',10)
ws.set_column(
'B:B',100)
ws.set_column(
'C:C',10)

# (x+1,y+1)의 위치에 데이터 입력 및 셀 속성 설정
ws.write(0,0,u'번호',format0)
ws.write(
0,1,u'제목',format0)
ws.write(
0,2,u'금액',format0)

# 엑셀 행을 바꾸기 위한 변수 init 할당
global init
init =
1

def write(count):
ws.write(init
,0,count,format1)
ws.write(init
,1,name[count-1],format1)
ws.write(init
,2,don[count-1],format1)
init +=
1

# 기부 컨텐츠 제목 및 기부 금액을 담을 리스트 할당
name = list()
don =
list()

# 기부 컨텐츠 제목 및 기부 금액 추출
def extract_title_and_money():
html = driver.page_source
soup = BeautifulSoup(html
, 'html.parser')
for title in soup.find('title'):
name.append(title)
print u"[+] 기부 완료 : {}".format(title)
item = soup.find(
'dl', {'class': 'detail_fund fund_belong'})
for person in item.find('dt', {'class': 'tit_fund'}):
for total in item.find('dd', {'class': 'txt_fund'}):
persons =
int(person[person.find('(') + 1:person.find(')') - 1].replace(',','')) # 응원기부 (xxx명)
totals = int(total.replace(u'원', '').replace(',', '')) # xx,xxx원
don.append(totals/persons)
print u"\t[-] 기부 금액은 {}원 입니다".format(totals/persons)

# 크롬 웹 드라이버를 이용한 다함께 카카오 페이지 오픈
driver = webdriver.Chrome('C:/Users/HighTech/Downloads/web/chromedriver')
driver.implicitly_wait(
1)
driver.get(
"https://together.kakao.com/fundraisings/now")

# 다함께 카카오 로그인 기능
driver.find_element_by_xpath('//*[@id="dkHead"]/div[1]/div[2]/a[2]').click()
driver.find_element_by_xpath(
'//*[@id="loginEmail"]').send_keys('카카오 이메일을 입력하세요')
driver.find_element_by_xpath(
'//*[@id="loginPw"]').send_keys('카카오 이메일의 비밀번호를 입력하세요')
driver.find_element_by_xpath(
'//*[@id="login-form"]/fieldset/button').click()

# 한 번에 볼 수 있는 게시물이 20개 이므로, 전체 게시물 보기 클릭.
# for i in range(7):
# driver.find_element_by_xpath('//*[@id="mArticle"]/div[3]/div[3]/button').click()

# 실제 기부 과정을 작동시키는 중심 코드
for j in range(1,141):
try :
driver.find_element_by_xpath(
'//*[@id="mArticle"]/div[3]/div[2]/ul/li['+str(j)+']/fundraising-card/a').click()
driver.find_element_by_xpath(
'//*[@id="txtCmt"]').send_keys(u'응원할게요')
driver.find_element_by_xpath(
'//*[@id="mArticle"]/comments/div/div[1]/div/div[2]/div/fieldset/button[2]').click()
extract_title_and_money()

write(j)
driver.back()
driver.find_element_by_xpath(
'//*[@id="toast-container"]/div[2]/div/div[2]/div').click()
if j%20==0:
driver.find_element_by_xpath(
'//*[@id="mArticle"]/div[3]/div[3]/button').click()
except :
pass
wb.close()

print "[+] 총 기부 횟수 = {}회".format(len(name))
print "[+] 총 기부 금액 = {}원".format(sum(don))


사용자 정의 함수 write를 사용하게 끔 다시 수정함 리얼 최종 완성.



[그림 1] - 6차 최종 완성 본 스크립트 실행 결과



[ 동영상 ] - 카카오 기부 자동화 스크립트 동작 과정 및 결과 출력 영상



'Coding' 카테고리의 다른 글

Crawling  (0) 2018.07.27
[Pcap Parser]  (0) 2018.07.22
원탁의 기사  (0) 2018.01.05
100 계단 오르기  (0) 2018.01.04
[ Parser ] Portable Executable Structure Parsing (PE 구조 분석)  (0) 2017.10.23

#About



아서왕(king Arthur)은 자기 딸과 결혼시킬 기사(knight) 한 사람만 남기고 모두 죽이기로 하였습니다.


자기가 빠진 12명의 기사를 원탁에 둘러앉히고, 1번 기사를 지나 2번 기사를 죽였습니다.


3번 기사를 지나 4번 기사를 죽였습니다. 이렇게 원탁을 돌면서 하나 건너 하나씩 죽였습니다.


결국 마지막 9번 기사만이 살아남아서 공주와 결혼하고 아서왕의 뒤를 이어 왕이 되었습니다.


 n명의 기사가 있다면 몇 번째 기사가 살아남아서 공주와 결혼하고 왕이 될까요?




문제의 배경


이 문제의 원형은 요셉의 문제(Josephus problem)이다. 요셉의 문제를 간추리면 다음과 같다.


'1세기 경, 40명의 이스라엘 독립군이 로마군에 쫓겨 동굴에 갇히자, 한 사람씩 건너뛰는 방법으로 모두 자살하기로 한다.


허나 마지막 한 사람은 자살하지 않고 로마군에 항복하여 살아난다. 그가 요셉이다. 


그는 계산된 위치에 서 있었기 때문이다. 사람 수에 따른 요셉의 위치는 어디 이겠는가?'





#Solution


일단 수작업으로 조사를 해보면 아래와 같이 기사의 수에 따른 생존자 위치를 확인할 수 있다


기사의 수  

1

3

10 

11 

12 

13 

14 

15 

16 

17 

18 

19 

20 

 생존자 위치

1

11

13 

15 


규칙을 확인해보면 기사의 수 보다 작은 동시에 가장 가까운 2의 n제곱 만큼이 생존자 위치임을 확인할 수 있다


ex) 기사의 수가 4명이라면 2의 2제곱이므로 1,3이 생존자 위치가 된다

ex) 기사의 수가 8명이라면 2의 3제곱이므로 1,3,5가 생존자 위치가 된다

ex) 기사의 수가 16명이라면 2의 4제곱이므로 1,3,5,7가 생존자 위치가 된다


① 기사의 수  

3

10 

11 

12 

13 

14 

15 

16 

17 

18 

19 

20 

② 2**n 

16 

16 

16 

16 

16 

(①- )

생존자 위치 

11 

13 

15 



(①- ②)와 생존자 위치에 대한 규칙을 확인해보면 () * 2 + 1이 생존자 위치임을 알 수 있다.


즉, 기사의 수를 n이라하면, n에서 n이하의 가장 큰 2의 제곱수를 빼고, 그 수에 2를 곱한 다음, 1을 더하면 생존 위치이다.


예를 들어 n=12이면, 12이하인 가장 큰 2의 제곱수는 8이므로 생존위치 = (12-8)*2+1=9가 되며 알고리즘으로 표현한 것은 다음과 같다


knight = int(input('기사의 수를 입력하시오 : '))
i,j = 2,0

while (i**j<=knight): #기사의 수보다 작거나 같은 동시에 가장 가까운 i의 j제곱일때 까지 루프 반복
square = i**j #i의 j제곱을 square 변수에 할당
j+=1 #loop를 위한 +1 카운트

life_location = (knight-square)*i+1 #생존자 위치가 결정되는 규칙

print ("생존자 위치는 {}번째 입니다".format(life_location))

[코드 1] - 원탁의 기사 코드


위와 같은 방법으로도 결과 값인 생존자 위치를 얻을 수 있지만 또 다른 방법으로도 가능하다.

 

n이하인 가장 큰 2의 제곱수는 2진수로 바꾸었을 때 가장 왼쪽(MSB)의 비트에 해당한다


그러므로 생존자 위치는 n을 2진수로 바꾸어 가장 왼쪽의 1을 떼어내어 오른쪽 끝에 더하면 된다.


ex) 12(10진수) ---> 1100(2진수), MSB를 떼어내면 100, 오른쪽 끝(LSB 위치)에 1을 더하면 1001(2진수) 즉, 9이다.


이러한 작업을 left rotate라고 하며 정리하면, n명의 기사가 있을 때의 생존자 위치는 n을 2진수로 바꾸어 1회 left rotate한 위치이다.


knight = int(input('기사의 수를 입력하시오 : '))

binary = bin(knight) #a='0b1100'
rotation=int(binary[3:]+binary[2],base=2)

print("생존자 위치는 {}번째 입니다".format(rotation))

[코드 2] - 다른 방법의 원탁의 기사 코드



[그림 1] - 코드 결과


+ Recent posts