[๐Ÿฅ‰ Bronze 1] ํ—ค๋”์— ๋ฐ•ํžˆ๋Š” ๋‘ ๋ฐ”์ดํŠธ โ€” DreamHack [CodeEngn] Malware L03 ํ’€์ด

2026-08-19ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅ‰ Bronze 1] ํ—ค๋”์— ๋ฐ•ํžˆ๋Š” ๋‘ ๋ฐ”์ดํŠธ โ€” DreamHack [CodeEngn] Malware L03 ํ’€์ด

์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค 10์ค„์„ ๋˜์ ธ ์ฃผ๊ณ  "๋ฌด์—‡์„ ํ•˜๋Š” ํ•จ์ˆ˜์ธ๊ฐ€"๋งŒ ๋ฌป๋Š”๋‹ค. ๋ชจ์–‘์€ ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์ธ๋ฐ, ๋ชจ์–‘๋งŒ ๋ณด๊ณ  ๋‹ต์„ ์ฐ๊ธฐ์—” ๊ทผ๊ฑฐ๊ฐ€ ์–‡๋‹ค. ๊ทธ๋ž˜์„œ ๋ฐฐํฌ๋ณธ์„ ํ•œ ๊ธ€์ž๋„ ์•ˆ ๊ณ ์น˜๊ณ  ์ปดํŒŒ์ผํ•ด tcpdump ๋กœ ์žก์€ ์ง„์งœ ํŒจํ‚ท์˜ ์ฒดํฌ์„ฌ ์ž๋ฆฌ 12๊ณณ๊ณผ ๋งž์ถฐ ๋ดค๋‹ค. ์ „๋ถ€ ์ผ์น˜ํ–ˆ๊ณ , ๋ค์œผ๋กœ ์ด ๋ฐœ์ทŒ๋ณธ์ด ๊ทœ๊ฒฉ์—์„œ ์–ด๊ธ‹๋‚˜๋Š” ์ž๋ฆฌ ์„ธ ๊ตฐ๋ฐ๊ฐ€ ๋‚˜์™”๋‹ค.

๋ฌธ์ œ: DreamHack โ€” [CodeEngn] Malware L03 ๋ถ„๋ฅ˜: Misc (์•…์„ฑ์ฝ”๋“œ ๋ถ„์„) ๋‚œ์ด๋„: ๐Ÿฅ‰ Bronze 1 FLAG: checksum

๋ฐฐํฌ ํŒŒ์ผ์€ ํ…์ŠคํŠธ ํ•œ ์žฅ์ด๊ณ , ๋ฌธ์ œ ์„ค๋ช…์€ ๋‘ ์ค„์ด๋‹ค.

# show_desc.sh
#!/bin/sh
# ๋“œ๋ฆผํ•ต API ์—์„œ ์ด ๋ฌธ์ œ์˜ ์ œ๋ชฉยท๋ถ„๋ฅ˜ยท์„ค๋ช…๋งŒ ๋ฝ‘์•„ ๋ณธ๋‹ค
python3 ~/Dev/Hacking_Project/_๋„๊ตฌ/dreamhack_auto/fetch_desc.py 370 | python3 -c '
import sys, json
d = json.load(sys.stdin)
print("์ œ๋ชฉ    :", d["title"].strip())
print("๋ถ„๋ฅ˜    :", ", ".join(d["tags"]))
print("๋‚œ์ด๋„  :", d["tier_display"])
print("ํ‘ผ ์‚ฌ๋žŒ :", d["cnt_solvers"], "๋ช…")
print()
print("[๋ฌธ์ œ ์„ค๋ช…]")
print(d["description"].strip())
print()
print("[ํžŒํŠธ]", d["hints"] or "์—†์Œ")
'
./show_desc.sh

๋“œ๋ฆผํ•ต API ๋กœ ๋ฐ›์€ CodeEngn Malware L03 ๋ฌธ์ œ ๋ฉ”ํƒ€ โ€” ๋ถ„๋ฅ˜ misc, ๋‚œ์ด๋„ Bronze 1, 120๋ช…์ด ํ•ด๊ฒฐ, ์„ค๋ช…์€ "๋‹ค์Œ์€ ์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค์˜ ์ผ๋ถ€๋ถ„์ด๋‹ค. ๋ฌด์—‡์„ ํ•˜๋Š” ํ•จ์ˆ˜์ธ๊ฐ€"์ด๊ณ  ํžŒํŠธ๋Š” ์—†๋‹ค
๋“œ๋ฆผํ•ต API ๋กœ ๋ฐ›์€ CodeEngn Malware L03 ๋ฌธ์ œ ๋ฉ”ํƒ€ โ€” ๋ถ„๋ฅ˜ misc, ๋‚œ์ด๋„ Bronze 1, 120๋ช…์ด ํ•ด๊ฒฐ, ์„ค๋ช…์€ "๋‹ค์Œ์€ ์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค์˜ ์ผ๋ถ€๋ถ„์ด๋‹ค. ๋ฌด์—‡์„ ํ•˜๋Š” ํ•จ์ˆ˜์ธ๊ฐ€"์ด๊ณ  ํžŒํŠธ๋Š” ์—†๋‹ค

ex) ์˜ˆ์‹œ์กฐ์ฐจ ์—†๊ณ  ํžŒํŠธ๋„ ์—†๋‹ค. ๊ฐ™์€ ์‹œ๋ฆฌ์ฆˆ Malware L02์™€ ํ˜•์‹์€ ๊ฐ™๋‹ค โ€” ์†Œ๋ฌธ์ž ํ•œ ๋‹จ์–ด, ๋„์–ด์“ฐ๊ธฐ ์—†์ด.


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…[CodeEngn] Malware L03 (DreamHack #370)
๋‚œ์ด๋„๐Ÿฅ‰ Bronze 1
๋ถ„๋ฅ˜Misc โ€” ์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค ๋ถ„์„
์ œ๊ณต ํŒŒ์ผ03.txt (308๋ฐ”์ดํŠธ, 10์ค„, CRLF)
์„œ๋ฒ„์—†์Œ (์˜คํ”„๋ผ์ธ ๋ฌธ์ œ)
ํ•ต์‹ฌRFC 1071 ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ โ€” ๋กœ์šฐ์†Œ์ผ“์œผ๋กœ ํ—ค๋”๋ฅผ ์ง์ ‘ ๋งŒ๋“œ๋Š” ์ฝ”๋“œ๊ฐ€ ์ปค๋„ ๋Œ€์‹  ์ฑ„์›Œ์•ผ ํ•˜๋Š” ๊ฐ’

ํ’€์ด ํ๋ฆ„์€ ๋‹จ์ˆœํ•˜๋‹ค. ์ฝ”๋“œ๋ฅผ ์ฝ๊ณ  "์ฒดํฌ์„ฌ ๊ฐ™๋‹ค"๊นŒ์ง€๋Š” ๊ธˆ๋ฐฉ ๊ฐ„๋‹ค. ๋ฌธ์ œ๋Š” ๊ทธ๋‹ค์Œ์ด๋‹ค. ์–ด๋–ค ์ฒดํฌ์„ฌ์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒŒ ์ •๋ง ๋งž๋Š”์ง€๋ฅผ ๋ฌด์—‡์œผ๋กœ ํ™•์ •ํ•˜๋А๋ƒ. ์ด ๊ธ€์€ ๊ทธ ํ™•์ • ๊ณผ์ •์ด ์ „๋ถ€๋‹ค.



๐Ÿ”ฌ ์ •์ฐฐ โ€” ๋ฐฐํฌ๋ณธ์€ 10์ค„์ด ์ „๋ถ€๋‹ค

file extracted/03.txt; wc -lc extracted/03.txt; sha256sum extracted/03.txt; cat extracted/03.txt

fileยทwcยทsha256sumยทcat ์ถœ๋ ฅ โ€” 03.txt ๋Š” CRLF ์ค„๋ฐ”๊ฟˆ ASCII ํ…์ŠคํŠธ 10์ค„ 308๋ฐ”์ดํŠธ์ด๊ณ  sha256 ์€ 18e1d30f ๋กœ ์‹œ์ž‘ํ•œ๋‹ค
fileยทwcยทsha256sumยทcat ์ถœ๋ ฅ โ€” 03.txt ๋Š” CRLF ์ค„๋ฐ”๊ฟˆ ASCII ํ…์ŠคํŠธ 10์ค„ 308๋ฐ”์ดํŠธ์ด๊ณ  sha256 ์€ 18e1d30f ๋กœ ์‹œ์ž‘ํ•œ๋‹ค

๋ฐฐํฌ๋ณธ ์ „๋ฌธ์€ ์ด๋ ‡๋‹ค.

u_short Malware_L03(u_short * data,u_short length) 
{
        register long value;
        u_short i;
        for(i=0;i<(length>>1);i++)
                value+=data[i];
        if((length&1)==1)
                value+=(data[i]<<8);
        value=(value&65535)+(value>>16);
        return(~value);
}

์ฝํžˆ๋Š” ๋Œ€๋กœ ์˜ฎ๊ธฐ๋ฉด ์ด๋ ‡๊ฒŒ ๋œ๋‹ค.

  • data ๋ฅผ 16๋น„ํŠธ ์›Œ๋“œ ๋ฐฐ์—ด๋กœ ๋ณด๊ณ  length>>1 ๊ฐœ๋ฅผ value ์— ๋”ํ•œ๋‹ค.
  • ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜๋ฉด ๋‚จ์€ ์ž๋ฆฌ๋ฅผ data[i]<<8 ๋กœ ํ•œ ๋ฒˆ ๋” ๋”ํ•œ๋‹ค.
  • (value&65535)+(value>>16) ์œผ๋กœ ์ƒ์œ„๋กœ ๋„˜์นœ ์บ๋ฆฌ๋ฅผ ํ•˜์œ„ 16๋น„ํŠธ์— ๋˜๋Œ๋ ค ๋”ํ•œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์— ~value ๋ฅผ 16๋น„ํŠธ๋กœ ์ž˜๋ผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์บ๋ฆฌ๋ฅผ ๋ฒ„๋ฆฌ์ง€ ์•Š๊ณ  ๋˜๋Œ๋ ค ๋”ํ•˜๋Š” ๋ง์…ˆ, ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ˆ˜๋กœ ๋’ค์ง‘์–ด ๋‚ด๋ณด๋‚ด๋Š” ๋งˆ๋ฌด๋ฆฌ. ์ด ์กฐํ•ฉ์€ 1์˜ ๋ณด์ˆ˜ ํ•ฉ, ์ฆ‰ ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์˜ ์ง€๋ฌธ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ๊นŒ์ง€๋Š” "๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค"๋Š” ๊ด€์ฐฐ์ผ ๋ฟ์ด๋‹ค. CRC ๊ณ„์—ด๋„, ๋‹จ์ˆœ ํ•ฉ๊ณ„๋„ ๊ฒ‰๋ชจ์Šต์€ ๋น„์Šทํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค.


๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์€ ์–ด๋””์— ์“ฐ์ด๋Š” ๊ฐ’์ธ๊ฐ€

IPv4 ํ—ค๋”์—๋Š” Header checksum ์ด๋ผ๋Š” 16๋น„ํŠธ ์ž๋ฆฌ๊ฐ€ ์žˆ๋‹ค. TCPยทUDPยทICMP ํ—ค๋”์—๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๊ณ„์‚ฐํ•œ ์ฒดํฌ์„ฌ ์ž๋ฆฌ๊ฐ€ ํ•˜๋‚˜์”ฉ ์žˆ๋‹ค.

IPv4 ํ—ค๋” ํ•„๋“œ ๋ฐฐ์น˜๋„ โ€” 20๋ฐ”์ดํŠธ ๊ณ ์ •๋ถ€์˜ ์„ธ ๋ฒˆ์งธ ํ–‰์— TTLยทProtocol ๊ณผ ๋‚˜๋ž€ํžˆ Header checksum ์ด๋ผ๋Š” 16๋น„ํŠธ ์ž๋ฆฌ๊ฐ€ ์žˆ๋‹ค
IPv4 ํ—ค๋” ํ•„๋“œ ๋ฐฐ์น˜๋„ โ€” 20๋ฐ”์ดํŠธ ๊ณ ์ •๋ถ€์˜ ์„ธ ๋ฒˆ์งธ ํ–‰์— TTLยทProtocol ๊ณผ ๋‚˜๋ž€ํžˆ Header checksum ์ด๋ผ๋Š” 16๋น„ํŠธ ์ž๋ฆฌ๊ฐ€ ์žˆ๋‹ค

์ถœ์ฒ˜: Wikimedia Commons, Michel Bakni, CC BY-SA 4.0

๊ณ„์‚ฐ ๊ทœ์น™์€ RFC 1071์— ์žˆ๋‹ค. ์š”์•ฝํ•˜๋ฉด ์„ธ ์ค„์ด๋‹ค.

  1. ๋ฐ์ดํ„ฐ๋ฅผ 16๋น„ํŠธ ์›Œ๋“œ๋กœ ๋Š์–ด 1์˜ ๋ณด์ˆ˜ ํ•ฉ์„ ๊ตฌํ•œ๋‹ค. ๋„˜์นœ ์บ๋ฆฌ๋Š” ๋ฒ„๋ฆฌ์ง€ ์•Š๊ณ  ํ•˜์œ„๋กœ ๋˜๋Œ๋ ค ๋”ํ•œ๋‹ค.
  2. ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜๋ฉด ๋งˆ์ง€๋ง‰ ๋ฐ”์ดํŠธ ์˜ค๋ฅธ์ชฝ์„ 0์œผ๋กœ ์ฑ„์›Œ 16๋น„ํŠธ ์›Œ๋“œ๋กœ ๋งŒ๋“ ๋‹ค.
  3. ํ•ฉ์˜ 1์˜ ๋ณด์ˆ˜๊ฐ€ ์ฒดํฌ์„ฌ์ด๋‹ค.

์ด ๋ฐฉ์‹์ด ์˜ค๋ž˜ ์‚ด์•„๋‚จ์€ ์ด์œ ๋Š” ์„ฑ์งˆ์ด ๋‘ ๊ฐœ ์žˆ์–ด์„œ๋‹ค. ๋ง์…ˆ์ด ๊ตํ™˜ยท๊ฒฐํ•ฉ๋ฒ•์น™์„ ๋งŒ์กฑํ•˜๋‹ˆ ์›Œ๋“œ๋ฅผ ์–ด๋–ค ์ˆœ์„œ๋กœ ๋”ํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๊ณ , ๋ฐ”์ดํŠธ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ” ๊ณ„์‚ฐํ•ด๋„ ๊ฒฐ๊ณผ์˜ ๋ฐ”์ดํŠธ ์ˆœ์„œ๋งŒ ๋ฐ”๋€๋‹ค. ๊ทธ๋ž˜์„œ ๋ผ์šฐํ„ฐ๊ฐ€ TTL ํ•˜๋‚˜ ๊นŽ์„ ๋•Œ ํ—ค๋” ์ „์ฒด๋ฅผ ๋‹ค์‹œ ํ›‘์ง€ ์•Š๊ณ  ์ฐจ๋ถ„๋งŒ ๋”ํ•ด์„œ ์ฒดํฌ์„ฌ์„ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฐฐํฌ๋ณธ์ด ํ•˜๋Š” ์ผ์„ ๊ทธ๋ฆผ ํ•œ ์žฅ์œผ๋กœ ์˜ฎ๊ธฐ๋ฉด ์ด๋ ‡๋‹ค. ๋ถ‰๊ฒŒ ํ‘œ์‹œํ•œ ์…‹์€ ๋’ค์—์„œ ๋”ฐ๋กœ ๋‹ค๋ฃฌ๋‹ค.

๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜์˜ ๊ณ„์‚ฐ ํ๋ฆ„๋„ โ€” ๋ฐ”์ดํŠธ๋ฅผ 16๋น„ํŠธ ์›Œ๋“œ๋กœ ์ฝ์–ด value ์— ๋ˆ„์‚ฐํ•˜๊ณ  ํ™€์ˆ˜ ๋ฐ”์ดํŠธ๋ฅผ 8๋น„ํŠธ ๋ฐ€์–ด ๋”ํ•œ ๋’ค ์บ๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ ์ ‘๊ณ  ๋ณด์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ดˆ๊ธฐํ™” ๋ˆ„๋ฝ๊ณผ ๋ฒ„ํผ ๋ฐ– ์ฝ๊ธฐ์™€ ํด๋”ฉ 1ํšŒ๊ฐ€ ๋ถ‰๊ฒŒ ํ‘œ์‹œ๋ผ ์žˆ๋‹ค
๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜์˜ ๊ณ„์‚ฐ ํ๋ฆ„๋„ โ€” ๋ฐ”์ดํŠธ๋ฅผ 16๋น„ํŠธ ์›Œ๋“œ๋กœ ์ฝ์–ด value ์— ๋ˆ„์‚ฐํ•˜๊ณ  ํ™€์ˆ˜ ๋ฐ”์ดํŠธ๋ฅผ 8๋น„ํŠธ ๋ฐ€์–ด ๋”ํ•œ ๋’ค ์บ๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ ์ ‘๊ณ  ๋ณด์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ดˆ๊ธฐํ™” ๋ˆ„๋ฝ๊ณผ ๋ฒ„ํผ ๋ฐ– ์ฝ๊ธฐ์™€ ํด๋”ฉ 1ํšŒ๊ฐ€ ๋ถ‰๊ฒŒ ํ‘œ์‹œ๋ผ ์žˆ๋‹ค



๐Ÿงช ์ฝ์ง€ ๋ง๊ณ  ๋Œ๋ ค ๋ณธ๋‹ค โ€” ๋ฐฐํฌ๋ณธ์„ ๊ทธ๋Œ€๋กœ ์ปดํŒŒ์ผ

๊ด€์ฐฐ์„ ์‚ฌ์‹ค๋กœ ๋ฐ”๊พธ๋ ค๋ฉด ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. 03.txt ๋Š” ํ•จ์ˆ˜ ํ•˜๋‚˜๋ฟ์ด๋ผ ๊ทธ๋Œ€๋กœ๋Š” ๋ชป ๋Œ๋ฆฌ๋‹ˆ, ํ•œ ๊ธ€์ž๋„ ๊ณ ์น˜์ง€ ์•Š๊ณ  ํ—ค๋” ํ•œ ์ค„๋งŒ ์–น์–ด ์ปดํŒŒ์ผ ๋‹จ์œ„๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

/* 03.txt (๋ฐฐํฌ๋ณธ) ์›๋ฌธ ๊ทธ๋Œ€๋กœ. CRLF ๋งŒ LF ๋กœ ๋ฐ”๊ฟจ๊ณ  ๊ทธ ๋ฐ–์—” ํ•œ ๊ธ€์ž๋„ ์†๋Œ€์ง€ ์•Š์•˜๋‹ค. */
#include <sys/types.h>   /* u_short */
 
u_short Malware_L03(u_short * data,u_short length) 
{
        register long value;
        u_short i;
        for(i=0;i<(length>>1);i++)
                value+=data[i];
        if((length&1)==1)
                value+=(data[i]<<8);
        value=(value&65535)+(value>>16);
        return(~value);
}

์—ฌ๊ธฐ์— 16์ง„ ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ ํ•จ์ˆ˜์— ๋จน์ด๋Š” ๊ป๋ฐ๊ธฐ๋ฅผ ๋ถ™์ธ๋‹ค.

/* driver.c โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ํ˜ธ์ถœํ•ด ๋ณด๋Š” ๊ป๋ฐ๊ธฐ.
 * ์‚ฌ์šฉ๋ฒ•: ./cksum <hex๋ฌธ์ž์—ด>          (์˜ˆ: ./cksum 4500003ca1b64000400600000a000001)
 *         hex ๋ฅผ ๋ฐ”์ดํŠธ๋กœ ํ’€์–ด Malware_L03(buf, len) ์„ ๋ถ€๋ฅด๊ณ  ๊ฒฐ๊ณผ๋ฅผ 16์ง„์ˆ˜๋กœ ์ฐ๋Š”๋‹ค. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
 
u_short Malware_L03(u_short * data, u_short length);   /* snippet.c */
 
int main(int argc, char **argv)
{
    static unsigned char buf[65536];
    size_t n = 0;
    const char *h;
 
    if (argc != 2) { fprintf(stderr, "usage: %s <hex>\n", argv[0]); return 2; }
    h = argv[1];
    if (strlen(h) % 2) { fprintf(stderr, "hex ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜๋‹ค\n"); return 2; }
 
    while (*h) {
        char b[3] = { h[0], h[1], 0 };
        buf[n++] = (unsigned char)strtoul(b, NULL, 16);
        h += 2;
    }
    printf("len=%zu  Malware_L03=0x%04x\n", n, Malware_L03((u_short *)buf, (u_short)n));
    return 0;
}
gcc -O0 -g -Wall -Wextra -o cksum snippet.c driver.c; ./cksum 0001f203f4f5f6f7; ./cksum 4500003c1c46400040060000ac100a63ac100a0c

gcc ๋นŒ๋“œ์™€ ๋‘ ๋ฒˆ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” 8๋ฐ”์ดํŠธ ์ž…๋ ฅ์— 0x0d22, 20๋ฐ”์ดํŠธ IP ํ—ค๋” ์ž…๋ ฅ์— 0xe6b1 ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๋Š” ์—†๋‹ค
gcc ๋นŒ๋“œ์™€ ๋‘ ๋ฒˆ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” 8๋ฐ”์ดํŠธ ์ž…๋ ฅ์— 0x0d22, 20๋ฐ”์ดํŠธ IP ํ—ค๋” ์ž…๋ ฅ์— 0xe6b1 ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๋Š” ์—†๋‹ค

์ฒซ ์ž…๋ ฅ 00 01 f2 03 f4 f5 f6 f7 ์€ RFC 1071 3์žฅ์ด ์˜ˆ์ œ๋กœ ์“ฐ๋Š” ๋ฐ”๋กœ ๊ทธ ๋ฐ”์ดํŠธ์—ด์ด๋‹ค. RFC ๋Š” ์—ฌ๊ธฐ์„œ 1์˜ ๋ณด์ˆ˜ ํ•ฉ์ด ddf2 ๋ผ๊ณ  ์ ์–ด ๋†จ๋‹ค. ์ฒดํฌ์„ฌ์€ ๊ทธ ๋ณด์ˆ˜๋‹ˆ๊นŒ 220d ์—ฌ์•ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์šฐ๋ฆฌ ํ•จ์ˆ˜๋Š” 0x0d22 ๋ฅผ ๋ฑ‰์—ˆ๋‹ค. ๋’ค์ง‘ํ˜€ ์žˆ๋‹ค.

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” ๋ฐ”์ดํŠธ๊ฐ€ ๋’ค์ง‘ํ˜€ ๋‚˜์™€์„œ ํ•œ์ฐธ ๋ถ™๋“ค๊ณ  ์žˆ์—ˆ๋‹ค

์ฒ˜์Œ์—๋Š” ์ด๊ฑธ ๋ถˆ์ผ์น˜๋กœ ๋ดค๋‹ค. 0d22 ์™€ 220d ๋Š” ๋‹ค๋ฅธ ์ˆ˜๋‹ˆ๊นŒ.

์ฐฉ๊ฐ์˜ ์ง€์ ์€ "๋ฐ˜ํ™˜๊ฐ’์„ ํ™”๋ฉด์— ์ฐ์€ 16์ง„์ˆ˜"์™€ "๊ทธ ๊ฐ’์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ–ˆ์„ ๋•Œ์˜ ๋ฐ”์ดํŠธ ์ˆœ์„œ"๋ฅผ ๊ฐ™์€ ๊ฒƒ์œผ๋กœ ๋ณธ ๋ฐ ์žˆ์—ˆ๋‹ค.

์ด ํ•จ์ˆ˜๋Š” ์›Œ๋“œ๋ฅผ ํ˜ธ์ŠคํŠธ ์ˆœ์„œ๋กœ ์ฝ๋Š”๋‹ค. x86-64 ๋Š” ๋ฆฌํ‹€์—”๋””์–ธ์ด๋ผ ๋ฉ”๋ชจ๋ฆฌ์˜ 45 00 ์„ u_short ๋กœ ์ฝ์œผ๋ฉด ์ˆ˜์น˜๋Š” 0x0045 ๋‹ค. ๊ทœ๊ฒฉ์ด ๋งํ•˜๋Š” ์›Œ๋“œ 0x4500 ๊ณผ ๋ฐ”์ดํŠธ๊ฐ€ ๋’ค์ง‘ํ˜€ ์žˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋’ค์ง‘ํžŒ ์ฑ„๋กœ ๊ณ„์† ๋”ํ•œ ๋’ค ๊ฒฐ๊ณผ u_short ๋ฅผ ๋‹ค์‹œ ๋ฉ”๋ชจ๋ฆฌ์— ์“ฐ๋ฉด ํ•œ ๋ฒˆ ๋” ๋’ค์ง‘ํžŒ๋‹ค. ๋‘ ๋ฒˆ ๋’ค์ง‘ํ˜”์œผ๋‹ˆ ์ „์„ ์— ๋‚˜๊ฐ€๋Š” ๋ฐ”์ดํŠธ๋Š” ๊ทœ๊ฒฉ๋Œ€๋กœ๋‹ค.

์ฆ‰ ํ™”๋ฉด์˜ 0x0d22 ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์“ฐ๋ฉด 22 0d ๊ฐ€ ๋˜๊ณ , ๊ทธ๊ฒŒ ๊ณง RFC ๊ฐ€ ๋งํ•œ 220d ๋‹ค. RFC 1071 3์žฅ์ด "Normal Order" ์™€ "Swapped Order" ๋‘ ์—ด์„ ๋‚˜๋ž€ํžˆ ๊ณ„์‚ฐํ•ด ๋ณด์—ฌ ์ฃผ๋Š” ์ด์œ ๊ฐ€ ์ •ํ™•ํžˆ ์ด๊ฒƒ์ด๋‹ค โ€” ์–ด๋А ์ชฝ์œผ๋กœ ๋”ํ•ด๋„ ๋งˆ์ง€๋ง‰์— ํ•œ ๋ฒˆ ๋’ค์ง‘์œผ๋ฉด ๊ฐ™์€ ๊ฐ’์ด ๋œ๋‹ค.

๊ทธ๋ž˜์„œ ์ดํ›„ ๋น„๊ต๋Š” ์ „๋ถ€ ์ „์„  ์ˆœ์„œ๋กœ ๋ฐ”๊ฟ”์„œ ํ•œ๋‹ค. reference.py ์˜ to_wire() ๊ฐ€ ๊ทธ ์ผ๋งŒ ํ•œ๋‹ค.

RFC ๋ฌธ์„œ๋ฅผ ์˜†์— ๋„์›Œ ๋†“๊ณ  ๊ฐ™์€ ํ™”๋ฉด์—์„œ ๋Œ€์กฐํ•ด ๋ณด๋ฉด ๋ช…ํ™•ํ•˜๋‹ค.

sed -n "254,269p" rfc1071.txt; ./cksum 0001f203f4f5f6f7

RFC 1071 3์žฅ ์˜ˆ์ œ ํ‘œ์™€ ๋ฐฐํฌ๋ณธ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ•œ ํ™”๋ฉด์— ๋†“์€ ๋ชจ์Šต โ€” ๋ฌธ์„œ์˜ Normal Order ์—ด ์ตœ์ข… ํ•ฉ์ด ddf2 ์ด๊ณ  ๋ฐฐํฌ๋ณธ์€ ๊ทธ ๋ณด์ˆ˜๋ฅผ ๋’ค์ง‘์€ 0x0d22 ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค
RFC 1071 3์žฅ ์˜ˆ์ œ ํ‘œ์™€ ๋ฐฐํฌ๋ณธ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ•œ ํ™”๋ฉด์— ๋†“์€ ๋ชจ์Šต โ€” ๋ฌธ์„œ์˜ Normal Order ์—ด ์ตœ์ข… ํ•ฉ์ด ddf2 ์ด๊ณ  ๋ฐฐํฌ๋ณธ์€ ๊ทธ ๋ณด์ˆ˜๋ฅผ ๋’ค์ง‘์€ 0x0d22 ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค

๋‘ ๋ฒˆ์งธ ์ž…๋ ฅ์€ ์ฒดํฌ์„ฌ ํ•„๋“œ๋ฅผ 0์œผ๋กœ ๋น„์šด 20๋ฐ”์ดํŠธ IP ํ—ค๋”๋‹ค. ๋ฐ˜ํ™˜๊ฐ’ 0xe6b1 ์„ ๋ฉ”๋ชจ๋ฆฌ ์ˆœ์„œ๋กœ ์“ฐ๋ฉด b1 e6 โ€” ์ด ํ—ค๋”์˜ ์ •๋‹ต ์ฒดํฌ์„ฌ 0xb1e6 ์ด๋‹ค.


๐Ÿ›  ์ปดํŒŒ์ผ ๊ฒฐ๊ณผ๋ฅผ ๋„๊ตฌ๋กœ ํ™•์ธ

์†Œ์Šค๋ฅผ ์ฝ์€ ๊ฒƒ๊ณผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋งŒ๋“  ๊ฒƒ์ด ๊ฐ™์€์ง€๋Š” ๋”ฐ๋กœ ๋ด์•ผ ํ•œ๋‹ค. ํŠนํžˆ register long value; ๊ฐ€ ์‹ค์ œ๋กœ ์–ด๋А ๋ ˆ์ง€์Šคํ„ฐ๋กœ ๊ฐ”๋Š”์ง€, ์บ๋ฆฌ ํด๋”ฉ์ด ๋ช‡ ๋ฒˆ ๋„๋Š”์ง€๊ฐ€ ๋’ค์—์„œ ์ค‘์š”ํ•ด์ง„๋‹ค.

๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ์— ์ฃผ์„์„ ์–น๋Š” ์น˜ํ™˜ ๊ทœ์น™์€ ํŒŒ์ผ๋กœ ๋”ฐ๋กœ ๋’€๋‹ค. ์ธ๋ผ์ธ์œผ๋กœ sed ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์“ฐ๋ฉด ๋”ฐ์˜ดํ‘œ๊ฐ€ ์…ธ์„ ์ง€๋‚˜๋ฉฐ ๊นจ์ง„๋‹ค.

# annotate.sed โ€” objdump ์ถœ๋ ฅ์— ์ฃผ์„๋งŒ ์–น๋Š”๋‹ค(๋ช…๋ นยท์ฃผ์†Œ๋Š” ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค).
s/\(movzx  eax,WORD PTR \[rax\]\)$/\1                 <-- 16๋น„ํŠธ ์›Œ๋“œ ํ•˜๋‚˜๋ฅผ ํ˜ธ์ŠคํŠธ ์ˆœ์„œ๋กœ ์ฝ๋Š”๋‹ค/
s/\(add    rbx,rax\)$/\1                          <-- value ๋Š” rbx. ์—ฌ๊ธฐ์„œ ๋ˆ„์‚ฐํ•œ๋‹ค/
s/\(shr    ax,1\)$/\1                            <-- length>>1 = ์›Œ๋“œ ๊ฐœ์ˆ˜/
s/\(and    eax,0x1\)$/\1                        <-- length \& 1 : ํ™€์ˆ˜ ๋ฐ”์ดํŠธ๊ฐ€ ๋‚จ์•˜๋‚˜/
s/\(shl    eax,0x8\)$/\1                        <-- ๋ฌธ์ œ์˜ data\[i\]<<8. 8๋น„ํŠธ ๋ฐ€์–ด ์˜ฌ๋ฆฐ๋‹ค/
s/\(movzx  eax,bx\)$/\1                        <-- value \& 65535/
s/\(sar    rdx,0x10\)$/\1                       <-- value >> 16/
s/\(lea    rbx,\[rax+rdx\*1\]\)$/\1               <-- ์บ๋ฆฌ ํด๋”ฉ. ๋”ฑ ํ•œ ๋ฒˆ๋ฟ์ด๋‹ค/
s/\(not    eax\)$/\1                           <-- ~value, ๋ฐ˜ํ™˜์€ ax 16๋น„ํŠธ๋กœ ์ž˜๋ฆฐ๋‹ค/
objdump -d --no-show-raw-insn -M intel cksum | sed -n "/<Malware_L03>:/,/ret/p" | sed -f annotate.sed

objdump ๋กœ ๋ฝ‘์€ Malware L03 ๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ์— ์ฃผ์„์„ ์–น์€ ํ™”๋ฉด โ€” value ๊ฐ€ rbx ์— ๋ฐฐ์ •๋˜๊ณ  shl eax 0x8 ๋กœ ํ™€์ˆ˜ ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ€์–ด ์˜ฌ๋ฆฌ๋ฉฐ lea rbx ๋กœ ์บ๋ฆฌ๋ฅผ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์ ‘๋Š”๋‹ค
objdump ๋กœ ๋ฝ‘์€ Malware L03 ๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ์— ์ฃผ์„์„ ์–น์€ ํ™”๋ฉด โ€” value ๊ฐ€ rbx ์— ๋ฐฐ์ •๋˜๊ณ  shl eax 0x8 ๋กœ ํ™€์ˆ˜ ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ€์–ด ์˜ฌ๋ฆฌ๋ฉฐ lea rbx ๋กœ ์บ๋ฆฌ๋ฅผ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์ ‘๋Š”๋‹ค

์„ธ ๊ฐ€์ง€๊ฐ€ ๋ณด์ธ๋‹ค.

์ฒซ์งธ, value ๋Š” rbx ๋‹ค. ํ•จ์ˆ˜ ์•ž๋จธ๋ฆฌ์—์„œ push rbx ๋กœ ํ˜ธ์ถœํ•œ ์ชฝ์˜ ๊ฐ’์„ ์ €์žฅํ•ด ๋‘๋Š”๋ฐ, ๊ทธ ๋’ค๋กœ rbx ๋ฅผ 0์œผ๋กœ ๋†“๋Š” ๋ช…๋ น์ด ์—†๋‹ค. ๊ณง์žฅ add rbx,rax ๋กœ ๋ˆ„์‚ฐ์ด ์‹œ์ž‘๋œ๋‹ค. ์†Œ์Šค์— ์ดˆ๊ธฐํ™”๊ฐ€ ์—†์œผ๋‹ˆ ๋‹น์—ฐํ•œ ๊ฒฐ๊ณผ๋‹ค.

๋‘˜์งธ, ํ™€์ˆ˜ ๋ฐ”์ดํŠธ ์ฒ˜๋ฆฌ๋Š” movzx eax,WORD PTR [rax] ๋’ค์— shl eax,0x8 ์ด๋‹ค. ์›Œ๋“œ ํ•˜๋‚˜๋ฅผ ํ†ต์งธ๋กœ ์ฝ๊ณ  8๋น„ํŠธ ๋ฐ€์–ด ์˜ฌ๋ฆฐ๋‹ค.

์…‹์งธ, ์บ๋ฆฌ ํด๋”ฉ์€ movzx eax,bx / sar rdx,0x10 / lea rbx,[rax+rdx*1] ์„ธ ๋ช…๋ น๋ฟ์ด๋‹ค. ์ ‘๋Š” ๋™์ž‘์ด ํ•œ ๋ฒˆ๋ฐ–์— ์—†๋‹ค.

์ •์ ์œผ๋กœ ์ฝ์€ ๊ฑธ ์‹คํ–‰ ์ค‘์—๋„ ํ™•์ธํ•œ๋‹ค. gdb ๋ฐฐ์น˜ ์Šคํฌ๋ฆฝํŠธ๋Š” ์ด๋ ‡๋‹ค.

# cmds.gdb โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ value(=rbx) ๋ฅผ ์‹ค์ œ๋กœ ๋“ค์—ฌ๋‹ค๋ณธ๋‹ค.
# ์ •์  ๋ถ„์„์—์„œ "value ๋Š” rbx ์— ์žกํ˜”๊ณ  ์ดˆ๊ธฐํ™”๊ฐ€ ์—†๋‹ค"๊ณ  ์ฝ์€ ๊ฒƒ์„ ๋Ÿฐํƒ€์ž„์œผ๋กœ ํ™•์ธํ•œ๋‹ค.
set confirm off
set pagination off
break Malware_L03
break *(Malware_L03 + 0x73)
run 4500003c1c46400040060000ac100a63ac100a0c
 
printf "[1] ์ง„์ž… ์งํ›„  rbx(=value ์ดˆ๊ธฐ๊ฐ’) = 0x%lx\n", $rbx
continue
 
printf "[2] ๋ˆ„์‚ฐ ๋๋‚œ ๋’ค rbx(=value)      = 0x%lx\n", $rbx
printf "    value & 65535 = 0x%04lx,  value >> 16 = 0x%lx\n", $rbx & 0xffff, $rbx >> 16
printf "    ํด๋”ฉ 1ํšŒ ๊ฒฐ๊ณผ  = 0x%lx  (์—ฌ๊ธฐ์„œ ๋ฉˆ์ถ˜๋‹ค)\n", ($rbx & 0xffff) + ($rbx >> 16)
x/4i $pc
finish
gdb -q -batch -x cmds.gdb --args ./cksum 4500003c1c46400040060000ac100a63ac100a0c

gdb ๋ฐฐ์น˜ ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํ•จ์ˆ˜ ์ง„์ž… ์‹œ rbx ๊ฐ€ 0x0 ์ด๊ณ  ๋ˆ„์‚ฐ์ด ๋๋‚œ ๋’ค 0x1194d ์ด๋ฉฐ ํด๋”ฉ 1ํšŒ ๊ฒฐ๊ณผ๊ฐ€ 0x194e ๋กœ ๋ฉˆ์ถ”๊ณ  ๋ฐ˜ํ™˜๊ฐ’์€ 59057 ์ด๋‹ค
gdb ๋ฐฐ์น˜ ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํ•จ์ˆ˜ ์ง„์ž… ์‹œ rbx ๊ฐ€ 0x0 ์ด๊ณ  ๋ˆ„์‚ฐ์ด ๋๋‚œ ๋’ค 0x1194d ์ด๋ฉฐ ํด๋”ฉ 1ํšŒ ๊ฒฐ๊ณผ๊ฐ€ 0x194e ๋กœ ๋ฉˆ์ถ”๊ณ  ๋ฐ˜ํ™˜๊ฐ’์€ 59057 ์ด๋‹ค

๋ˆ„์‚ฐ์ด ๋๋‚œ ์‹œ์ ์˜ value ๊ฐ€ 0x1194d ๋‹ค. 16๋น„ํŠธ๋ฅผ ๋„˜๊ฒผ์œผ๋‹ˆ ํด๋”ฉ์ด ํ•„์š”ํ•˜๊ณ , ํ•œ ๋ฒˆ ์ ‘์œผ๋ฉด 0x194e ๊ฐ€ ๋œ๋‹ค. ์ด๋ฒˆ์—” ๊ทธ ๊ฐ’์ด ๋‹ค์‹œ 16๋น„ํŠธ๋ฅผ ๋„˜์ง€ ์•Š์•„์„œ ๊ฒฐ๊ณผ๊ฐ€ ๋งž์•˜๋‹ค. ๋ฐ˜ํ™˜๊ฐ’ 59057 ์€ 0xe6b1 ์ด๋‹ค.

"์ด๋ฒˆ์—” ์•ˆ ๋„˜์—ˆ๋‹ค"๋Š” ๋ง์€ ๋’ค์ง‘์œผ๋ฉด ๋„˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค. ๊ทธ ์–˜๊ธฐ๋Š” ์กฐ๊ธˆ ๋’ค์—.



๐Ÿ› ์ฒซ ๋นŒ๋“œ๊ฐ€ ๋งž์€ ๊ฑด ์šด์ด์—ˆ๋‹ค

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” ๊ฒฝ๊ณ  ํ•˜๋‚˜ ์—†์ด ๋นŒ๋“œ๋˜๊ธธ๋ž˜ ๋ฉ€์ฉกํ•œ ์ฝ”๋“œ์ธ ์ค„ ์•Œ์•˜๋‹ค

-Wall -Wextra ๋ฅผ ๋ถ™์—ฌ ๋นŒ๋“œํ–ˆ๋Š”๋ฐ ๊ฒฝ๊ณ ๊ฐ€ ํ•œ ์ค„๋„ ์•ˆ ๋‚˜์™”๋‹ค. ๊ทธ๋ž˜์„œ ๋„˜์–ด๊ฐ”๋‹ค.

์ตœ์ ํ™”๋ฅผ ์ผœ ๋ณด๊ณ ์„œ์•ผ ์•Œ์•˜๋‹ค.

gcc -O2 -Wall -Wextra -o cksum_O2 snippet.c driver.c

gcc -O2 ๋นŒ๋“œ ๊ฒฝ๊ณ  โ€” snippet.c 6๋ฒˆ ์ค„์˜ register long value ๊ฐ€ ์ดˆ๊ธฐํ™” ์—†์ด ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉฐ Wmaybe-uninitialized ๊ฒฝ๊ณ ๋ฅผ ๋‚ธ๋‹ค
gcc -O2 ๋นŒ๋“œ ๊ฒฝ๊ณ  โ€” snippet.c 6๋ฒˆ ์ค„์˜ register long value ๊ฐ€ ์ดˆ๊ธฐํ™” ์—†์ด ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉฐ Wmaybe-uninitialized ๊ฒฝ๊ณ ๋ฅผ ๋‚ธ๋‹ค

-Wmaybe-uninitialized ๋Š” ๋ฐ์ดํ„ฐ ํ๋ฆ„ ๋ถ„์„์ด ํ•„์š”ํ•ด์„œ -O0 ์—์„œ๋Š” ์•„์˜ˆ ์ผœ์ง€์ง€ ์•Š๋Š”๋‹ค. ์ตœ์ ํ™” ์—†์ด ๋นŒ๋“œํ•˜๋ฉด ์ด ์ฝ”๋“œ๋Š” ์กฐ์šฉํžˆ ํ†ต๊ณผํ•œ๋‹ค.

๊ทธ๋Ÿผ -O0 ๋นŒ๋“œ๋Š” ์™œ ์ •๋‹ต์„ ๋ƒˆ๋‚˜. value ๊ฐ€ rbx ์— ์žกํ˜”๊ณ , main ์ด ๊ทธ ์‹œ์ ์— rbx ์— ๋งˆ์นจ 0์„ ๋“ค๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์šฐ์—ฐ์ด๋‹ค.

์šฐ์—ฐ์ด๋ผ๋Š” ๊ฑธ ๋ณด์ด๋ ค๋ฉด rbx ๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์ •ํ•ด์„œ ๋„ฃ์–ด ๋ณด๋ฉด ๋œ๋‹ค. ์–ด์…ˆ๋ธ”๋ฆฌ ๊ป๋ฐ๊ธฐ ํ•˜๋‚˜๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค.

/* dirty_rbx.S โ€” ํ˜ธ์ถœ ์ง์ „ rbx ์— ์›ํ•˜๋Š” ๊ฐ’์„ ๋„ฃ๊ณ  ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋ฅผ ๋ถ€๋ฅธ๋‹ค.
 *
 * ์™œ rbx ๋ƒ: 03.txt ์˜ register long value ๋ฅผ gcc ๊ฐ€ rbx ์— ๋ฐฐ์ •ํ•˜๋Š”๋ฐ,
 * ์ดˆ๊ธฐํ™”๊ฐ€ ์—†์–ด์„œ "ํ˜ธ์ถœํ•œ ์ชฝ์ด rbx ์— ๋‚จ๊ฒจ ๋‘” ๊ฐ’"์ด ๊ทธ๋Œ€๋กœ ์ฒซ ๋ˆ„์‚ฐ๊ฐ’์ด ๋œ๋‹ค.
 * ๊ทธ๊ฒŒ ์šฐ์—ฐํžˆ 0 ์ด๋ฉด ์ •์ƒ ๋™์ž‘์ฒ˜๋Ÿผ ๋ณด์ด๊ณ , ์•„๋‹ˆ๋ฉด ์ฒดํฌ์„ฌ์ด ํ†ต์งธ๋กœ ์–ด๊ธ‹๋‚œ๋‹ค.
 *
 * long call_dirty(void *data, unsigned short len, unsigned long seed);
 *   rdi=data, esi=len, rdx=seed
 */
    .text
    .globl  call_dirty
    .type   call_dirty, @function
call_dirty:
    push    %rbx
    mov     %rdx, %rbx          /* value ๊ฐ€ ์‹œ์ž‘ํ•  ์“ฐ๋ ˆ๊ธฐ๊ฐ’์„ ์šฐ๋ฆฌ๊ฐ€ ์ •ํ•œ๋‹ค */
    call    Malware_L03@PLT     /* rbx ๋Š” callee-saved ๋ผ PLT/ld.so ๋Š” ์•ˆ ๊ฑด๋“œ๋ฆฐ๋‹ค */
    pop     %rbx
    ret
    .size   call_dirty, .-call_dirty
    .section .note.GNU-stack,"",@progbits
/* uninit_demo.c โ€” "register long value;" ์— ์ดˆ๊ธฐํ™”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒŒ ์‹ค์ œ๋กœ ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋‚˜.
 *
 * ๊ฐ™์€ ์ž…๋ ฅ์„ ์ฃผ๊ณ  ํ˜ธ์ถœ ์ง์ „ rbx ๊ฐ’๋งŒ ๋ฐ”๊ฟ” ๊ฐ€๋ฉฐ ๋ถ€๋ฅธ๋‹ค.
 * ๋นŒ๋“œ:  gcc -O0 -g -o uninit_demo snippet.c dirty_rbx.S uninit_demo.c
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
 
long call_dirty(void *data, unsigned short len, unsigned long seed);   /* dirty_rbx.S */
 
int main(void)
{
    /* ์•ž์—์„œ ์“ด ๊ต๊ณผ์„œ IP ํ—ค๋”(์ฒดํฌ์„ฌ ํ•„๋“œ๋Š” 0). ์ •๋‹ต์€ ์ „์„  ์ˆœ์„œ๋กœ 0xb1e6 */
    static const unsigned char hdr[20] = {
        0x45,0x00,0x00,0x3c, 0x1c,0x46,0x40,0x00, 0x40,0x06,0x00,0x00,
        0xac,0x10,0x0a,0x63, 0xac,0x10,0x0a,0x0c
    };
    unsigned long seeds[] = { 0, 1, 0x10, 0xdead, 0xffffffff, 0x7fffffffffffffffUL };
    size_t i;
 
    puts("ํ˜ธ์ถœ ์ง์ „ rbx    ๋ฐ˜ํ™˜๊ฐ’(ํ˜ธ์ŠคํŠธ)  ์ „์„  ์ˆœ์„œ   RFC1071(0xb1e6)๊ณผ");
    for (i = 0; i < sizeof(seeds) / sizeof(seeds[0]); i++) {
        unsigned short r = (unsigned short)call_dirty((void *)hdr, sizeof(hdr), seeds[i]);
        unsigned short wire = (unsigned short)((r << 8) | (r >> 8));
        printf("0x%-16lx 0x%04x          0x%04x      %s\n",
               seeds[i], r, wire, wire == 0xb1e6 ? "์ผ์น˜" : "โ˜…๋ถˆ์ผ์น˜");
    }
    return 0;
}
gcc -O0 -g -o uninit_demo snippet.c dirty_rbx.S uninit_demo.c; ./uninit_demo

ํ˜ธ์ถœ ์ง์ „ rbx ๊ฐ’์„ ๋ฐ”๊ฟ” ๊ฐ€๋ฉฐ ๊ฐ™์€ IP ํ—ค๋”์˜ ์ฒดํฌ์„ฌ์„ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ โ€” rbx ๊ฐ€ 0 ์ผ ๋•Œ๋งŒ 0xb1e6 ๋กœ ์ผ์น˜ํ•˜๊ณ  1ยท0x10ยท0xdead ๋“ฑ์—์„œ๋Š” ์ „๋ถ€ ๋‹ค๋ฅธ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค
ํ˜ธ์ถœ ์ง์ „ rbx ๊ฐ’์„ ๋ฐ”๊ฟ” ๊ฐ€๋ฉฐ ๊ฐ™์€ IP ํ—ค๋”์˜ ์ฒดํฌ์„ฌ์„ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ โ€” rbx ๊ฐ€ 0 ์ผ ๋•Œ๋งŒ 0xb1e6 ๋กœ ์ผ์น˜ํ•˜๊ณ  1ยท0x10ยท0xdead ๋“ฑ์—์„œ๋Š” ์ „๋ถ€ ๋‹ค๋ฅธ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค

rbx ๊ฐ€ 0์ผ ๋•Œ๋งŒ ๋งž๋Š”๋‹ค. 0xdead ํ•˜๋‚˜ ๋“ค์–ด ์žˆ์œผ๋ฉด ์ฒดํฌ์„ฌ์€ 0x0408 ์ด ๋˜๊ณ , ๊ทธ ํŒจํ‚ท์€ ์ˆ˜์‹  ์ธก์—์„œ ๊ทธ๋ƒฅ ๋ฒ„๋ ค์ง„๋‹ค.

์‹ค์ œ ์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค์—์„œ ์ด ์ค„์ด ์›๋ž˜ register long value = 0; ์ด์—ˆ๋Š”์ง€๋Š” ์•Œ ์ˆ˜ ์—†๋‹ค. ๋ฌธ์ œ๋กœ ๋ฐฐํฌ๋œ ๋ฐœ์ทŒ๋ณธ์—๋Š” ์ดˆ๊ธฐํ™”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ๋งŒ์ด ํ™•์‹คํ•˜๋‹ค.


๐Ÿ’ฃ ๊ฒฐํ•จ ์…‹ โ€” ๊ทœ๊ฒฉ๊ณผ ๋‹ค๋ฅธ ์ž๋ฆฌ

๋ฐฐํฌ๋ณธ์ด ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์„ ์˜๋„ํ•œ๋‹ค๋Š” ๊ฑด ์ด์ œ ๋ถ„๋ช…ํ•˜๋‹ค. ๊ทธ๋Ÿผ ๊ทœ๊ฒฉ๋Œ€๋กœ ํ•˜๊ณ  ์žˆ๋‚˜. ์ด๊ฑธ ์žฌ๋ ค๋ฉด ๋น„๊ต ๋Œ€์ƒ์ด ์žˆ์–ด์•ผ ํ•˜๋‹ˆ RFC 1071 ์„ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ธด ์ •๋‹ต์ง€๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

#!/usr/bin/env python3
"""reference.py โ€” RFC 1071 ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์„ ๊ทœ๊ฒฉ ๊ทธ๋Œ€๋กœ ๋…๋ฆฝ ๊ตฌํ˜„ํ•œ ๊ฒƒ.
๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜(03.txt)์™€ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•œ '์ •๋‹ต์ง€' ์—ญํ• ๋งŒ ํ•œ๋‹ค.
 
RFC 1071 ยง1:
  (1) ๋ฐ์ดํ„ฐ๋ฅผ 16๋น„ํŠธ ๋น…์—”๋””์–ธ ์›Œ๋“œ๋กœ ๋Š์–ด 1์˜ ๋ณด์ˆ˜ ํ•ฉ์„ ๊ตฌํ•œ๋‹ค(์บ๋ฆฌ๋Š” ๋˜๋Œ๋ ค ๋”ํ•œ๋‹ค).
  (2) ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜๋ฉด ๋งˆ์ง€๋ง‰ ๋ฐ”์ดํŠธ ์˜ค๋ฅธ์ชฝ์„ 0์œผ๋กœ ์ฑ„์›Œ 16๋น„ํŠธ ์›Œ๋“œ๋กœ ๋งŒ๋“ ๋‹ค.
  (3) ํ•ฉ์˜ 1์˜ ๋ณด์ˆ˜๊ฐ€ ์ฒดํฌ์„ฌ์ด๋‹ค.
๋ฐ˜ํ™˜๊ฐ’์€ '์ „์„  ์œ„์— ๊ทธ๋Œ€๋กœ ์‹ค๋ฆฌ๋Š”' ๋น…์—”๋””์–ธ 16๋น„ํŠธ ์ •์ˆ˜๋‹ค.
"""
 
 
def rfc1071(data: bytes) -> int:
    if len(data) & 1:
        data = data + b"\x00"          # (2) ์˜ค๋ฅธ์ชฝ 0 ํŒจ๋”ฉ
    total = 0
    for off in range(0, len(data), 2):
        total += (data[off] << 8) | data[off + 1]      # (1) ๋น…์—”๋””์–ธ ์›Œ๋“œ
        total = (total & 0xFFFF) + (total >> 16)       #     ์บ๋ฆฌ ๋˜๋Œ๋ฆฌ๊ธฐ
    while total >> 16:
        total = (total & 0xFFFF) + (total >> 16)
    return (~total) & 0xFFFF                            # (3)
 
 
def snippet_model(data: bytes) -> int:
    """03.txt ๋ฅผ ๋ฆฌํ‹€์—”๋””์–ธ ๊ธฐ๊ณ„์—์„œ ๋Œ๋ ธ์„ ๋•Œ๋ฅผ ํŒŒ์ด์ฌ์œผ๋กœ ์˜ฎ๊ธด ๊ฒƒ.
    - ์›Œ๋“œ๋Š” ํ˜ธ์ŠคํŠธ(LE) ์ˆœ์„œ๋กœ ์ฝ๋Š”๋‹ค
    - ํ™€์ˆ˜ ๋ฐ”์ดํŠธ ์ฒ˜๋ฆฌ๋Š” data[i]<<8 ๊ทธ๋Œ€๋กœ (๋ฒ„ํผ ๋ฐ– 1๋ฐ”์ดํŠธ๋ฅผ ๊ฐ™์ด ์ฝ๋Š”๋‹ค)
    - ์บ๋ฆฌ ํด๋”ฉ์€ ์›๋ฌธ๋Œ€๋กœ '๋‹จ ํ•œ ๋ฒˆ'
    - ๋ฐ˜ํ™˜์€ u_short ์ ˆ๋‹จ
    ์ด ํ•จ์ˆ˜๊ฐ€ ๋ฑ‰๋Š” ๊ฐ’์€ ํ˜ธ์ŠคํŠธ ์ˆœ์„œ๋‹ค. ์ „์„  ์œ„ ๊ฐ’๊ณผ ๋น„๊ตํ•˜๋ ค๋ฉด ๋ฐ”์ดํŠธ๋ฅผ ๋’ค์ง‘์–ด์•ผ ํ•œ๋‹ค.
    """
    n = len(data)
    buf = data + b"\x00"               # OOB 1๋ฐ”์ดํŠธ๋ฅผ 0์œผ๋กœ ๊ฐ€์ •(์ •์ ๋ฒ„ํผ์˜ ํ”ํ•œ ๊ฒฝ์šฐ)
    value = 0                          # ์›๋ฌธ์€ ์ดˆ๊ธฐํ™”๊ฐ€ ์—†๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” 0 ์œผ๋กœ ๋‘”๋‹ค
    i = 0
    while i < (n >> 1):
        value += buf[2 * i] | (buf[2 * i + 1] << 8)     # LE u_short
        i += 1
    if n & 1:
        value += (buf[2 * i] | (buf[2 * i + 1] << 8)) << 8
    value = (value & 65535) + (value >> 16)             # ํด๋”ฉ 1ํšŒ๋ฟ
    return (~value) & 0xFFFF                            # u_short ์ ˆ๋‹จ
 
 
def to_wire(host_u16: int) -> int:
    """LE ๊ธฐ๊ณ„์—์„œ u_short ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๊ทธ๋Œ€๋กœ ์“ฐ๋ฉด ์ „์„  ์œ„์—์„œ๋Š” ๋ฐ”์ดํŠธ๊ฐ€ ๋’ค์ง‘ํ˜€ ๋ณด์ธ๋‹ค."""
    return ((host_u16 & 0xFF) << 8) | (host_u16 >> 8)
 
 
if __name__ == "__main__":
    import sys
    raw = bytes.fromhex(sys.argv[1])
    print(f"len={len(raw)}  rfc1071(wire)=0x{rfc1071(raw):04x}  "
          f"snippet(host)=0x{snippet_model(raw):04x}  "
          f"snippet(wire)=0x{to_wire(snippet_model(raw)):04x}")

ํ™€์ˆ˜ ๊ธธ์ด โ€” ๋ฉ”์‹œ์ง€ ๋ฐ– 1๋ฐ”์ดํŠธ๋ฅผ ๊ฐ™์ด ๋”ํ•œ๋‹ค

data ๋Š” u_short* ๋‹ค. ๋ฃจํ”„๊ฐ€ ๋๋‚œ ์‹œ์ ์— i ๋Š” length>>1 ์ด๊ณ , data[i] ๋Š” ์˜คํ”„์…‹ 2i ์™€ 2i+1 ๋‘ ๋ฐ”์ดํŠธ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜๋ฉด 2i ๊ฐ€ ๋งˆ์ง€๋ง‰ ์œ ํšจ ๋ฐ”์ดํŠธ์ด๋ฏ€๋กœ 2i+1 ์€ ๋ฉ”์‹œ์ง€ ๋ฐ–์ด๋‹ค.

7๋ฐ”์ดํŠธ ๋ฉ”์‹œ์ง€๋ฅผ 8๋ฐ”์ดํŠธ ๋ฒ„ํผ์— ๋‹ด๊ณ  8๋ฒˆ์งธ ๋ฐ”์ดํŠธ๋งŒ ๋ฐ”๊ฟ” ๋ณด๋ฉด ๋ฐ”๋กœ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

/* oob_demo.c โ€” ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜์ผ ๋•Œ data[i] ๊ฐ€ ์ •๋ง ๋ฒ„ํผ ๋ฐ–์„ ์ฝ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
 *
 * ๋ฉ”์‹œ์ง€๋Š” 7๋ฐ”์ดํŠธ๋ฟ์ธ๋ฐ data ๋Š” u_short* ๋ผ data[3] ์€ 8๋ฒˆ์งธ ๋ฐ”์ดํŠธ๊นŒ์ง€ ๋Œ์–ด์˜จ๋‹ค.
 * ๊ทธ 8๋ฒˆ์งธ ๋ฐ”์ดํŠธ๋งŒ ๋ฐ”๊ฟ” ๊ฐ€๋ฉฐ ๊ฐ™์€ 7๋ฐ”์ดํŠธ ๋ฉ”์‹œ์ง€์˜ ์ฒดํฌ์„ฌ์ด ํ”๋“ค๋ฆฌ๋Š”์ง€ ๋ณธ๋‹ค.
 *
 * ๋นŒ๋“œ:  gcc -O0 -g -o oob_demo snippet.c oob_demo.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
 
u_short Malware_L03(u_short *data, u_short length);   /* snippet.c */
 
int main(void)
{
    static const unsigned char msg[7] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07 };
    unsigned char guards[] = { 0x00, 0x41, 0xff };
    size_t g;
 
    printf("๋ฉ”์‹œ์ง€ 7๋ฐ”์ดํŠธ: 01 02 03 04 05 06 07  (๊ธธ์ด ์ธ์ž length=7 ๋กœ ๊ณ ์ •)\n\n");
    printf("๋ฒ„ํผ ๋ฐ– 8๋ฒˆ์งธ ๋ฐ”์ดํŠธ   ๋ฐ˜ํ™˜๊ฐ’(ํ˜ธ์ŠคํŠธ)\n");
    for (g = 0; g < sizeof(guards); g++) {
        unsigned char *p = malloc(8);
        memcpy(p, msg, 7);
        p[7] = guards[g];                       /* ๋ฉ”์‹œ์ง€๊ฐ€ ์•„๋‹Œ ์ž๋ฆฌ */
        printf("0x%02x                   0x%04x\n", guards[g], Malware_L03((u_short *)p, 7));
        free(p);
    }
    printf("\n๊ฐ™์€ ๋ฉ”์‹œ์ง€์ธ๋ฐ ๊ฐ’์ด ๋‹ฌ๋ผ์ง€๋ฉด, ํ•จ์ˆ˜๊ฐ€ ๋ฉ”์‹œ์ง€ ๋ฐ– 1๋ฐ”์ดํŠธ๋ฅผ ๊ฐ™์ด ๋”ํ•œ ๊ฒƒ์ด๋‹ค.\n");
    return 0;
}
gcc -O0 -g -Wall -o oob_demo snippet.c oob_demo.c; ./oob_demo

7๋ฐ”์ดํŠธ ๋ฉ”์‹œ์ง€์˜ ์ฒดํฌ์„ฌ์ด ๋ฒ„ํผ ๋ฐ– 8๋ฒˆ์งธ ๋ฐ”์ดํŠธ ๊ฐ’์— ๋”ฐ๋ผ 0xecf6ยท0xecb5ยท0xebf7 ๋กœ ๋‹ฌ๋ผ์ง€๋Š” ์‹คํ–‰ ๊ฒฐ๊ณผ
7๋ฐ”์ดํŠธ ๋ฉ”์‹œ์ง€์˜ ์ฒดํฌ์„ฌ์ด ๋ฒ„ํผ ๋ฐ– 8๋ฒˆ์งธ ๋ฐ”์ดํŠธ ๊ฐ’์— ๋”ฐ๋ผ 0xecf6ยท0xecb5ยท0xebf7 ๋กœ ๋‹ฌ๋ผ์ง€๋Š” ์‹คํ–‰ ๊ฒฐ๊ณผ

๋ฉ”์‹œ์ง€๋Š” ๊ทธ๋Œ€๋กœ์ธ๋ฐ ๊ฒฐ๊ณผ๊ฐ€ ์…‹ ๋‹ค ๋‹ค๋ฅด๋‹ค. ํ•จ์ˆ˜๊ฐ€ ๋ฉ”์‹œ์ง€๊ฐ€ ์•„๋‹Œ ๋ฐ”์ดํŠธ๋ฅผ ๊ณ„์‚ฐ์— ๋„ฃ์—ˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

์‹œํ”„ํŠธ ๋ฐฉํ–ฅ๋„ ์–ด๊ธ‹๋‚˜ ์žˆ๋‹ค. ๊ทœ๊ฒฉ์€ ๋งˆ์ง€๋ง‰ ํ™€์ˆ˜ ๋ฐ”์ดํŠธ์˜ ์˜ค๋ฅธ์ชฝ์„ 0์œผ๋กœ ์ฑ„์šฐ๋ผ๊ณ  ํ•œ๋‹ค. BSD ๊ณ„์—ด in_cksum ์€ ์ด๊ฑธ *(u_char *)(&answer) = *(u_char *)w; ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ, 16๋น„ํŠธ ๋ณ€์ˆ˜์˜ ์ฒซ ๋ฐ”์ดํŠธ์— ๊ทธ๋Œ€๋กœ ์จ ๋„ฃ๋Š” ๋ฐฉ์‹์ด๋ผ ๋ฆฌํ‹€์—”๋””์–ธ์—์„œ๋Š” ํ•˜์œ„ ๋ฐ”์ดํŠธ, ๋น…์—”๋””์–ธ์—์„œ๋Š” ์ƒ์œ„ ๋ฐ”์ดํŠธ๊ฐ€ ๋œ๋‹ค. ์–ด๋А ์ชฝ์ด๋“  ๊ทœ๊ฒฉ๊ณผ ๋งž๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์›Œ๋“œ๋ฅผ ํ†ต์งธ๋กœ ์ฝ์–ด 8๋น„ํŠธ ๋ฐ€์–ด ์˜ฌ๋ฆฌ๋ฏ€๋กœ ๋‘˜ ๋‹ค ์•„๋‹ˆ๋‹ค.

๋Œ€ํ˜• ๋ฒ„ํผ โ€” ์บ๋ฆฌ ํด๋”ฉ์ด ํ•œ ๋ฒˆ๋ฟ์ด๋‹ค

(value&65535)+(value>>16) ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค์‹œ 16๋น„ํŠธ๋ฅผ ๋„˜์„ ์ˆ˜ ์žˆ๋‹ค. value = 65536q + r ๋กœ ๋‘๋ฉด ์ด ์‹์€ q + r ์ธ๋ฐ, r ์ด ํฌ๊ณ  q ๊ฐ€ 1 ์ด์ƒ์ด๋ฉด ํ•ฉ์ด 65536์„ ๋„˜๊ธด๋‹ค. ํ‘œ์ค€ ๊ตฌํ˜„์ด sum += (sum >> 16); ์„ ํ•œ ์ค„ ๋” ๋‘๋Š” ์ด์œ ๋‹ค.

๋‘ ๊ฒฐํ•จ์„ ํ•œ ๋ฒˆ์— ์žฌ๋ ค๊ณ  ๋ฌด์ž‘์œ„ ์ž…๋ ฅ์œผ๋กœ ์ •๋‹ต์ง€์™€ ๋งž๋Œ€ ๋ดค๋‹ค.

#!/usr/bin/env python3
"""difftest.py โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜(์ปดํŒŒ์ผํ•œ ./cksum)์™€ RFC 1071 ์ •๋‹ต์ง€๋ฅผ ๋ฌด์ž‘์œ„ ์ž…๋ ฅ์œผ๋กœ ๋งž๋Œ€ ๋ณธ๋‹ค.
 
'์ด ํ•จ์ˆ˜๊ฐ€ ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์ด๋‹ค'๋ฅผ ๋ˆˆ์ด ์•„๋‹ˆ๋ผ ์‹ค์ธก์œผ๋กœ ํ™•์ •ํ•˜๋Š” ๊ฒŒ ๋ชฉ์ ์ด๋‹ค.
๊ธธ์ด๋Œ€(์ง์ˆ˜ ์†Œํ˜• / ํ™€์ˆ˜ / ์ง์ˆ˜ ๋Œ€ํ˜•)๋งˆ๋‹ค ์ผ์น˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ๊ณ , ์–ด๊ธ‹๋‚œ ๊ฒƒ์€ ์ฐจ์ด๊ฐ’ ๋ถ„ํฌ๋กœ ์š”์•ฝํ•œ๋‹ค.
"""
import collections
import random
import subprocess
 
from reference import rfc1071, to_wire
 
random.seed(20261208)          # ์žฌํ˜„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ณ ์ • (๋ฌธ์ œ ๊ณต๊ฐœ์ผ)
BIN = "./cksum"
 
 
def run_c(raw: bytes) -> int:
    """์ปดํŒŒ์ผํ•œ ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋ฅผ ์‹ค์ œ๋กœ ์‹คํ–‰ํ•ด ํ˜ธ์ŠคํŠธ ์ˆœ์„œ u_short ๋ฅผ ๋ฐ›์•„์˜จ๋‹ค."""
    out = subprocess.run([BIN, raw.hex()], capture_output=True, text=True, check=True).stdout
    return int(out.split("=")[-1], 16)
 
 
def sweep(lengths, label):
    ok = 0
    deltas = collections.Counter()
    sample = None
    for n in lengths:
        raw = bytes(random.randrange(256) for _ in range(n))
        got, want = to_wire(run_c(raw)), rfc1071(raw)
        if got == want:
            ok += 1
        else:
            deltas[want - got] += 1
            if sample is None:
                sample = (raw, got, want)
    bad = sum(deltas.values())
    print(f"[{label:<22}] ํ‘œ๋ณธ {ok + bad:>3}  ์ผ์น˜ {ok:>3}  ๋ถˆ์ผ์น˜ {bad:>3}")
    if bad:
        top = ", ".join(f"{d:+d}: {c}ํšŒ" for d, c in deltas.most_common(4))
        print(f"      ์ฐจ์ด(RFC1071 - ๋ฐฐํฌ๋ณธ) ๋ถ„ํฌ: {top}")
        raw, got, want = sample
        print(f"      ์ฒซ ์‚ฌ๋ก€ len={len(raw)} data={raw[:12].hex()}...  "
              f"๋ฐฐํฌ๋ณธ=0x{got:04x}  RFC1071=0x{want:04x}")
    return ok, bad
 
 
print("=== ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜ vs RFC 1071 ์ •๋‹ต์ง€ (์ž…๋ ฅ์€ ์‹œ๋“œ ๊ณ ์ • ๋‚œ์ˆ˜) ===")
sweep([random.randrange(1, 400) * 2 for _ in range(300)], "์ง์ˆ˜ 2~798B")
sweep([random.randrange(0, 400) * 2 + 1 for _ in range(300)], "ํ™€์ˆ˜ 1~799B")
sweep([random.randrange(20000, 60000) & ~1 for _ in range(120)], "์ง์ˆ˜ 20K~60KB")
python3 difftest.py

difftest.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์ง์ˆ˜ ๊ธธ์ด 2์—์„œ 798๋ฐ”์ดํŠธ๋Š” 300๊ฐœ ์ „๋ถ€ ์ผ์น˜ํ•˜๊ณ  ํ™€์ˆ˜ ๊ธธ์ด๋Š” 300๊ฐœ ์ค‘ 299๊ฐœ๊ฐ€ ๋ถˆ์ผ์น˜ํ•˜๋ฉฐ 20K์—์„œ 60KB ์ง์ˆ˜ ๊ธธ์ด๋Š” 120๊ฐœ ์ค‘ 10๊ฐœ๊ฐ€ ์ •ํ™•ํžˆ 256๋งŒํผ ์–ด๊ธ‹๋‚œ๋‹ค
difftest.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์ง์ˆ˜ ๊ธธ์ด 2์—์„œ 798๋ฐ”์ดํŠธ๋Š” 300๊ฐœ ์ „๋ถ€ ์ผ์น˜ํ•˜๊ณ  ํ™€์ˆ˜ ๊ธธ์ด๋Š” 300๊ฐœ ์ค‘ 299๊ฐœ๊ฐ€ ๋ถˆ์ผ์น˜ํ•˜๋ฉฐ 20K์—์„œ 60KB ์ง์ˆ˜ ๊ธธ์ด๋Š” 120๊ฐœ ์ค‘ 10๊ฐœ๊ฐ€ ์ •ํ™•ํžˆ 256๋งŒํผ ์–ด๊ธ‹๋‚œ๋‹ค

์ฝ๋Š” ๋ฒ•์ด ์…‹์œผ๋กœ ๊ฐˆ๋ฆฐ๋‹ค.

์ง์ˆ˜ ๊ธธ์ด ์†Œํ˜•์€ 300๊ฐœ ์ „๋ถ€ ์ผ์น˜. ์—ฌ๊ธฐ๊ฐ€ ๊ฒฐ๋ก ์˜ ๋ผˆ๋Œ€๋‹ค. ๊ทœ๊ฒฉ ๊ตฌํ˜„๊ณผ ํ•œ ๋น„ํŠธ๋„ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค.

ํ™€์ˆ˜ ๊ธธ์ด๋Š” 299๊ฐœ ๋ถˆ์ผ์น˜. ์ฐจ์ด๊ฐ€ ์ œ๊ฐ๊ฐ์ธ ๊ฒƒ๋„ ์•ž์˜ ๋ฒ„ํผ ๋ฐ– ์ฝ๊ธฐ์™€ ๋งž์•„๋–จ์–ด์ง„๋‹ค โ€” ๋”ธ๋ ค ๋“ค์–ด์˜จ ๋ฐ”์ดํŠธ๊ฐ€ ๋งค๋ฒˆ ๋‹ค๋ฅด๋‹ˆ๊นŒ.

๋Œ€ํ˜• ์ง์ˆ˜ ๊ธธ์ด๋Š” 10๊ฐœ ๋ถˆ์ผ์น˜์ธ๋ฐ ์ฐจ์ด๊ฐ€ ์ „๋ถ€ ์ •ํ™•ํžˆ -256. ์ „์„  ์ˆœ์„œ์—์„œ 256 ์ฐจ์ด๋Š” ํ˜ธ์ŠคํŠธ ์ˆœ์„œ์—์„œ 1 ์ฐจ์ด๋‹ค. ์ ‘๋‹ค ๋งŒ ์บ๋ฆฌ ํ•˜๋‚˜๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‚จ์€ ๊ฒƒ์ด๋‹ค.

์ด ์บ๋ฆฌ ๊ฒฐํ•จ์ด ์–ผ๋งˆ๋‚˜ ์งง์€ ์ž…๋ ฅ์—์„œ๋„ ํ„ฐ์ง€๋Š”์ง€ ๋”ฐ๋กœ ์žฌ ๋ดค๋‹ค.

#!/usr/bin/env python3
"""minimal_carry.py โ€” '์บ๋ฆฌ ํด๋”ฉ 1ํšŒ' ๊ฒฐํ•จ์„ ํ„ฐ๋œจ๋ฆฌ๋Š” ๊ฐ€์žฅ ์งง์€ ์ž…๋ ฅ์„ ์ฐพ๋Š”๋‹ค.
 
value = 65536*q + r ๋กœ ๋‘๋ฉด (value&65535)+(value>>16) = q+r ์ด๋‹ค.
์ด ๊ฐ’์ด ๋‹ค์‹œ 65536 ์„ ๋„˜์œผ๋ฉด ํด๋”ฉ์ด ํ•œ ๋ฒˆ ๋” ํ•„์š”ํ•œ๋ฐ ๋ฐฐํฌ๋ณธ์€ ๊ฑฐ๊ธฐ์„œ ๋ฉˆ์ถ˜๋‹ค.
q+r >= 65536 ์ด ๋˜๋ ค๋ฉด ์›Œ๋“œ ์ˆ˜ k >= q+2 ์—ฌ์•ผ ํ•˜๋ฏ€๋กœ ์ตœ์†Œ k=3, ์ฆ‰ 6๋ฐ”์ดํŠธ๋‹ค.
"""
import itertools
import subprocess
 
from reference import rfc1071, to_wire
 
 
def run_c(raw: bytes) -> int:
    out = subprocess.run(["./cksum", raw.hex()], capture_output=True, text=True, check=True).stdout
    return int(out.split("=")[-1], 16)
 
 
def le(w):                      # ํ˜ธ์ŠคํŠธ(LE) u_short ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ”์ดํŠธ๋กœ
    return bytes([w & 0xFF, w >> 8])
 
 
print("์›Œ๋“œ ์ˆ˜ k ๋ฅผ 2๋ถ€ํ„ฐ ์˜ฌ๋ฆฌ๋ฉฐ ๋ฐ˜๋ก€๊ฐ€ ๋‚˜์˜ค๋Š” ์ฒซ ์ง€์ ์„ ์ฐพ๋Š”๋‹ค")
for k in range(2, 6):
    hit = None
    # ๊ฐ ์›Œ๋“œ๋ฅผ 0xffff ๋กœ ์ฑ„์šฐ๊ณ  ๋งˆ์ง€๋ง‰ ํ•˜๋‚˜๋งŒ ํ›‘๋Š” ๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•˜๋‹ค
    for last in range(0, 0x10000):
        raw = le(0xFFFF) * (k - 1) + le(last)
        value = 0xFFFF * (k - 1) + last
        if ((value & 65535) + (value >> 16)) >> 16:
            hit = (raw, last)
            break
    if hit is None:
        print(f"  k={k} ({k*2}B): ๋ฐ˜๋ก€ ์—†์Œ")
        continue
    raw, last = hit
    got, want = to_wire(run_c(raw)), rfc1071(raw)
    print(f"  k={k} ({k*2}B): ๋ฐ˜๋ก€ ๋ฐœ๊ฒฌ  data={raw.hex()}  (๋งˆ์ง€๋ง‰ ์›Œ๋“œ 0x{last:04x})")
    print(f"      ๋ฐฐํฌ๋ณธ(์ „์„ ์ˆœ์„œ)=0x{got:04x}   RFC1071=0x{want:04x}   โ†’  {'๋‹ค๋ฆ„' if got != want else '๊ฐ™์Œ'}")
    break
python3 minimal_carry.py

minimal carry.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์›Œ๋“œ 2๊ฐœ 4๋ฐ”์ดํŠธ์—์„œ๋Š” ๋ฐ˜๋ก€๊ฐ€ ์—†๊ณ  ์›Œ๋“œ 3๊ฐœ 6๋ฐ”์ดํŠธ์—์„œ ffffffff0100 ์ด ๋ฐฐํฌ๋ณธ์€ 0xffff ๊ทœ๊ฒฉ์€ 0xfeff ๋กœ ๊ฐˆ๋ฆฐ๋‹ค
minimal carry.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์›Œ๋“œ 2๊ฐœ 4๋ฐ”์ดํŠธ์—์„œ๋Š” ๋ฐ˜๋ก€๊ฐ€ ์—†๊ณ  ์›Œ๋“œ 3๊ฐœ 6๋ฐ”์ดํŠธ์—์„œ ffffffff0100 ์ด ๋ฐฐํฌ๋ณธ์€ 0xffff ๊ทœ๊ฒฉ์€ 0xfeff ๋กœ ๊ฐˆ๋ฆฐ๋‹ค

6๋ฐ”์ดํŠธ๋‹ค. ๋Œ€์šฉ๋Ÿ‰ ํŽ˜์ด๋กœ๋“œ์—์„œ๋งŒ ๋‚˜์˜ค๋Š” ํฌ๊ท€ํ•œ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ, ์›Œ๋“œ ์„ธ ๊ฐœ์งœ๋ฆฌ ์ž…๋ ฅ์—์„œ ์ด๋ฏธ ๊ฐˆ๋ฆฐ๋‹ค.



๐ŸŽฏ ๊ฒฐ์ •์  ์ฆ๊ฑฐ โ€” ์ง„์งœ ํŒจํ‚ท๊ณผ ๋งž์ถฐ ๋ณธ๋‹ค

์—ฌ๊ธฐ๊นŒ์ง€๋Š” ์ „๋ถ€ ๋‚ด๊ฐ€ ๋งŒ๋“  ์ž…๋ ฅ์ด๋‹ค. ๋งˆ์ง€๋ง‰ ํ™•์ธ์€ ์ปค๋„์ด ์ง์ ‘ ๊ณ„์‚ฐํ•ด ์ „์„ ์— ์˜ฌ๋ฆฐ ๊ฐ’๊ณผ ๋งž๋Œ€๋Š” ๊ฒƒ์œผ๋กœ ํ•œ๋‹ค.

๋ฃจํ”„๋ฐฑ์œผ๋กœ ping ์„ ์„ธ ๋ฒˆ ์˜๊ณ  tcpdump ๋กœ ์žก๋Š”๋‹ค.

#!/usr/bin/env bash
# capture_live.sh โ€” ์ง„์งœ ํŒจํ‚ท์„ ํ•˜๋‚˜ ์žก์•„ ์˜จ๋‹ค.
# ๋ฃจํ”„๋ฐฑ์œผ๋กœ ping ์„ 3๋ฒˆ ์˜๊ณ  tcpdump ๋กœ pcap ์„ ๋‚จ๊ธด๋‹ค. ๋งŒ๋“ค์–ด๋‚ธ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ
# ์ปค๋„์ด ์ง์ ‘ ์ฒดํฌ์„ฌ์„ ์ฑ„์›Œ ์ „์„ ์— ์˜ฌ๋ฆฐ ๋ฐ”์ดํŠธ์—ฌ์•ผ ๋น„๊ต์— ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค.
set -euo pipefail
cd "$(dirname "$0")"
OUT=${1:-live_icmp.pcap}
 
sudo -n tcpdump -i lo -c 6 -s 0 -w "$OUT" icmp >/dev/null 2>&1 &
TD=$!
sleep 1
ping -c 3 -i 0.3 -s 32 127.0.0.1 >/dev/null
wait $TD || true
sudo -n chown "$(id -un)":"$(id -gn)" "$OUT"
ls -l "$OUT"
tcpdump -r "$OUT" -n -c 6 2>/dev/null
rm -f live_icmp.pcap && ./capture_live.sh

capture live.sh ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” tcpdump ๊ฐ€ ๋ฃจํ”„๋ฐฑ์—์„œ ICMP echo request ์™€ reply ๋ฅผ ๊ฐ 3๊ฐœ์”ฉ ์ด 6๊ฐœ ์žก์•„ live icmp.pcap 564๋ฐ”์ดํŠธ๋กœ ์ €์žฅํ–ˆ๋‹ค
capture live.sh ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” tcpdump ๊ฐ€ ๋ฃจํ”„๋ฐฑ์—์„œ ICMP echo request ์™€ reply ๋ฅผ ๊ฐ 3๊ฐœ์”ฉ ์ด 6๊ฐœ ์žก์•„ live icmp.pcap 564๋ฐ”์ดํŠธ๋กœ ์ €์žฅํ–ˆ๋‹ค

ping ์ด ๋งŒ๋“  ๊ฒƒ๋„, ์ปค๋„์ด ๋˜๋Œ๋ ค ์ค€ ๊ฒƒ๋„ ์šฐ๋ฆฌ ์†์„ ๊ฑฐ์น˜์ง€ ์•Š์€ ๊ฐ’์ด๋‹ค. ์ด์ œ ์ด pcap ์„ ํŒŒ์‹ฑํ•ด IP ํ—ค๋”์™€ ICMP ๋ฉ”์‹œ์ง€์˜ ์ฒดํฌ์„ฌ ์ž๋ฆฌ๋ฅผ 0์œผ๋กœ ๋˜๋Œ๋ฆฐ ๋’ค, ์ปดํŒŒ์ผํ•œ ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜์— ๊ทธ๋Œ€๋กœ ๋จน์ธ๋‹ค.

#!/usr/bin/env python3
"""verify_live.py โ€” ์‹ค์ œ๋กœ ์ „์„ ์„ ์ง€๋‚˜๊ฐ„ ํŒจํ‚ท์˜ ์ฒดํฌ์„ฌ์„ ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด ๋ณธ๋‹ค.
 
capture_live.sh ๊ฐ€ tcpdump ๋กœ ๋‚จ๊ธด pcap ์„ ์ฝ์–ด
  ยท IP ํ—ค๋” ์ฒดํฌ์„ฌ
  ยท ICMP ๋ฉ”์‹œ์ง€ ์ฒดํฌ์„ฌ
๋‘ ์ž๋ฆฌ๋ฅผ 0 ์œผ๋กœ ๋˜๋Œ๋ฆฐ ๋’ค ์ปดํŒŒ์ผํ•œ ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜(./cksum)์— ๊ทธ๋Œ€๋กœ ๋จน์ธ๋‹ค.
์ปค๋„์ด ์‹ค์ œ๋กœ ์จ ๋„ฃ์€ ๊ฐ’๊ณผ ํ•œ ๋น„ํŠธ๋ผ๋„ ๋‹ค๋ฅด๋ฉด '์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์ด๋‹ค'๋ผ๋Š” ๊ฒฐ๋ก ์ด ๋ฌด๋„ˆ์ง„๋‹ค.
"""
import struct
import subprocess
import sys
 
from reference import to_wire
 
PCAP = sys.argv[1] if len(sys.argv) > 1 else "live_icmp.pcap"
 
 
def run_c(raw: bytes) -> int:
    out = subprocess.run(["./cksum", raw.hex()], capture_output=True, text=True, check=True).stdout
    return int(out.split("=")[-1], 16)
 
 
def packets(path):
    blob = open(path, "rb").read()
    magic = blob[:4]
    endian = "<" if magic in (b"\xd4\xc3\xb2\xa1", b"\x4d\x3c\xb2\xa1") else ">"
    linktype = struct.unpack(endian + "I", blob[20:24])[0]
    off = 24
    while off + 16 <= len(blob):
        _, _, caplen, _ = struct.unpack(endian + "IIII", blob[off:off + 16])
        yield linktype, blob[off + 16: off + 16 + caplen]
        off += 16 + caplen
 
 
L2LEN = {0: 4, 1: 14, 113: 16, 101: 0}          # NULL / EN10MB / LINUX_SLL / RAW
 
print(f"pcap: {PCAP}")
rows = 0
for linktype, frame in packets(PCAP):
    ip = frame[L2LEN.get(linktype, 14):]
    if not ip or ip[0] >> 4 != 4:
        continue
    ihl = (ip[0] & 0xF) * 4
    hdr, payload = ip[:ihl], ip[ihl:]
    proto = hdr[9]
 
    # --- IP ํ—ค๋” ---
    on_wire_ip = struct.unpack("!H", hdr[10:12])[0]
    zeroed_ip = hdr[:10] + b"\x00\x00" + hdr[12:]
    calc_ip = to_wire(run_c(zeroed_ip))
 
    # --- ICMP ๋ฉ”์‹œ์ง€ (์˜์‚ฌํ—ค๋” ์—†์Œ) ---
    on_wire_l4 = calc_l4 = None
    if proto == 1 and len(payload) >= 4:
        on_wire_l4 = struct.unpack("!H", payload[2:4])[0]
        zeroed_l4 = payload[:2] + b"\x00\x00" + payload[4:]
        calc_l4 = to_wire(run_c(zeroed_l4))
 
    kind = {8: "echo request", 0: "echo reply"}.get(payload[0] if payload else -1, "?")
    okip = "์ผ์น˜" if calc_ip == on_wire_ip else "โ˜…๋ถˆ์ผ์น˜"
    print(f"  [{kind:<13}] IPํ—ค๋” {ihl}B  ์ „์„ =0x{on_wire_ip:04x} ๋ฐฐํฌ๋ณธ=0x{calc_ip:04x} {okip}")
    if calc_l4 is not None:
        okl4 = "์ผ์น˜" if calc_l4 == on_wire_l4 else "โ˜…๋ถˆ์ผ์น˜"
        print(f"  {'':<16} ICMP {len(payload)}B  ์ „์„ =0x{on_wire_l4:04x} ๋ฐฐํฌ๋ณธ=0x{calc_l4:04x} {okl4}")
    rows += 1
 
print(f"๊ฒ€์‚ฌํ•œ ํŒจํ‚ท {rows}๊ฐœ")
python3 verify_live.py

verify live.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํŒจํ‚ท 6๊ฐœ์˜ IP ํ—ค๋” ์ฒดํฌ์„ฌ๊ณผ ICMP ์ฒดํฌ์„ฌ ์ด 12์ž๋ฆฌ๊ฐ€ ์ „์„ ์— ์‹ค๋ฆฐ ๊ฐ’๊ณผ ๋ฐฐํฌ๋ณธ ๊ณ„์‚ฐ๊ฐ’์ด ๋ชจ๋‘ ์ผ์น˜ํ•œ๋‹ค
verify live.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํŒจํ‚ท 6๊ฐœ์˜ IP ํ—ค๋” ์ฒดํฌ์„ฌ๊ณผ ICMP ์ฒดํฌ์„ฌ ์ด 12์ž๋ฆฌ๊ฐ€ ์ „์„ ์— ์‹ค๋ฆฐ ๊ฐ’๊ณผ ๋ฐฐํฌ๋ณธ ๊ณ„์‚ฐ๊ฐ’์ด ๋ชจ๋‘ ์ผ์น˜ํ•œ๋‹ค

12๊ณณ ์ „๋ถ€ ์ผ์น˜. ํ—ค๋” 20๋ฐ”์ดํŠธ๋„ ์ง์ˆ˜, ICMP ๋ฉ”์‹œ์ง€ 40๋ฐ”์ดํŠธ๋„ ์ง์ˆ˜๋ผ ์•ž์—์„œ ๋ณธ ๊ฒฐํ•จ์ด ๋ฐœํ™”ํ•˜์ง€ ์•Š๋Š” ๊ตฌ๊ฐ„์ด๋‹ค. ์ด ํ•จ์ˆ˜๋Š” IP ํ—ค๋” ์ฒดํฌ์„ฌ์ด๊ณ  ICMP ์ฒดํฌ์„ฌ์ด๋ฉฐ, ๊ฐ™์€ ๊ณ„์‚ฐ์ด TCPยทUDP ์—๋„ ๊ทธ๋Œ€๋กœ ์“ฐ์ธ๋‹ค.


๐Ÿš€ ์›๋ž˜ ์žˆ์–ด์•ผ ํ•  ์ž๋ฆฌ์— ๊ฝ‚์•„ ๋ณธ๋‹ค

๊ทธ๋Ÿผ ์•…์„ฑ์ฝ”๋“œ๋Š” ์ด ํ•จ์ˆ˜๋ฅผ ์™œ ๋“ค๊ณ  ๋‹ค๋‹ˆ๋‚˜. ๋ณดํ†ต ์†Œ์ผ“์œผ๋กœ ๋ณด๋‚ด๋ฉด ์ปค๋„์ด ์ฒดํฌ์„ฌ์„ ์•Œ์•„์„œ ์ฑ„์›Œ ์ค€๋‹ค. ๊ทธ๋Ÿฐ๋ฐ IP_HDRINCL ์˜ต์…˜์„ ์ผ  ๋กœ์šฐ์†Œ์ผ“์œผ๋กœ IP ํ—ค๋”๋ฅผ ์ง์ ‘ ์จ์„œ ๋ณด๋‚ด๋ฉด ์ปค๋„์€ ์†๋Œ€์ง€ ์•Š๋Š”๋‹ค. ์ถœ๋ฐœ์ง€ ์ฃผ์†Œ๋ฅผ ์œ„์กฐํ•˜๋ ค๋ฉด ์ด ๊ฒฝ๋กœ๋ฅผ ์จ์•ผ ํ•˜๊ณ , ๊ทธ ์ˆœ๊ฐ„๋ถ€ํ„ฐ IP ์ฒดํฌ์„ฌ๋„ TCP ์ฒดํฌ์„ฌ๋„ ์ง์ ‘ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค.

๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋ฅผ ๊ทธ ์ž๋ฆฌ์— ๊ทธ๋Œ€๋กœ ๋„ฃ์–ด SYN ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค์–ด ๋ดค๋‹ค. ์ถœ๋ฐœ์ง€๋Š” 127.0.0.2 ๋กœ ์œ„์กฐํ–ˆ๊ณ  ๋ชฉ์ ์ง€๋Š” 127.0.0.1 ์ด๋ผ ํŒจํ‚ท์€ ๋ฃจํ”„๋ฐฑ ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€์ง€ ์•Š๋Š”๋‹ค.

/* craft_send.c โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋ฅผ '์›๋ž˜ ์ž๋ฆฌ'์— ๊ทธ๋Œ€๋กœ ๊ฝ‚์•„ ๋ณธ๋‹ค.
 *
 * IP_HDRINCL ๋กœ IP ํ—ค๋”๋ฅผ ์ง์ ‘ ์“ฐ๋Š” ๋กœ์šฐ์†Œ์ผ“์—์„œ๋Š” ์ปค๋„์ด IPยทTCP ์ฒดํฌ์„ฌ์„
 * ์ฑ„์›Œ ์ฃผ์ง€ ์•Š๋Š”๋‹ค. ์ถœ๋ฐœ์ง€ ์ฃผ์†Œ๋ฅผ ์œ„์กฐํ•˜๋Š” ํ”Œ๋Ÿฌ๋”๊ฐ€ 03.txt ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ
 * ๋ฐ˜๋“œ์‹œ ๋“ค๊ณ  ๋‹ค๋‹ˆ๋Š” ์ด์œ ๊ฐ€ ์ด๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” SYN ํ•œ ๊ฐœ๋งŒ ๋งŒ๋“ค์–ด
 * 127.0.0.2 -> 127.0.0.1:9 ๋กœ ๋ฃจํ”„๋ฐฑ์—๋งŒ ํ˜๋ฆฐ๋‹ค(์™ธ๋ถ€๋กœ ๋‚˜๊ฐ€์ง€ ์•Š๋Š”๋‹ค).
 *
 * ๋นŒ๋“œ:  gcc -O0 -g -o craft_send snippet.c craft_send.c
 * ์‹คํ–‰:  sudo ./craft_send            (๋กœ์šฐ์†Œ์ผ“์ด๋ผ root ํ•„์š”)
 */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
 
u_short Malware_L03(u_short *data, u_short length);   /* snippet.c โ€” ๋ฐฐํฌ๋ณธ ๊ทธ๋Œ€๋กœ */
 
/* TCP ์ฒดํฌ์„ฌ์€ IP ํ—ค๋”์—์„œ ๋นŒ๋ ค ์˜จ ์˜์‚ฌํ—ค๋”(12B)๊นŒ์ง€ ํฌํ•จํ•ด ๊ณ„์‚ฐํ•œ๋‹ค (RFC 793) */
struct pseudo {
    u_int32_t src, dst;
    u_int8_t  zero, proto;
    u_int16_t len;
};
 
int main(void)
{
    unsigned char pkt[sizeof(struct iphdr) + sizeof(struct tcphdr)];
    unsigned char pbuf[sizeof(struct pseudo) + sizeof(struct tcphdr)];
    struct iphdr  *ip  = (struct iphdr *)pkt;
    struct tcphdr *tcp = (struct tcphdr *)(pkt + sizeof(struct iphdr));
    struct pseudo  ph;
    struct sockaddr_in to;
    int s, on = 1;
 
    memset(pkt, 0, sizeof(pkt));
 
    ip->version = 4;  ip->ihl = 5;  ip->tos = 0;
    ip->tot_len = htons(sizeof(pkt));
    ip->id      = htons(0xC0DE);
    ip->frag_off = 0;  ip->ttl = 64;  ip->protocol = IPPROTO_TCP;
    ip->saddr = inet_addr("127.0.0.2");        /* ์œ„์กฐํ•œ ์ถœ๋ฐœ์ง€ */
    ip->daddr = inet_addr("127.0.0.1");
    ip->check = 0;
    ip->check = Malware_L03((u_short *)ip, sizeof(struct iphdr));   /* โ† ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜ */
 
    tcp->source = htons(31337);
    tcp->dest   = htons(9);                    /* discard ํฌํŠธ */
    tcp->seq    = htonl(0x1337BEEF);
    tcp->doff   = 5;
    tcp->syn    = 1;
    tcp->window = htons(1024);
    tcp->check  = 0;
 
    ph.src = ip->saddr;  ph.dst = ip->daddr;
    ph.zero = 0;  ph.proto = IPPROTO_TCP;  ph.len = htons(sizeof(struct tcphdr));
    memcpy(pbuf, &ph, sizeof(ph));
    memcpy(pbuf + sizeof(ph), tcp, sizeof(struct tcphdr));
    tcp->check = Malware_L03((u_short *)pbuf, sizeof(pbuf));        /* โ† ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜ */
 
    printf("IP  ์ฒดํฌ์„ฌ(๋ฐฐํฌ๋ณธ ๊ณ„์‚ฐ) = 0x%04x\n", ntohs(ip->check));
    printf("TCP ์ฒดํฌ์„ฌ(๋ฐฐํฌ๋ณธ ๊ณ„์‚ฐ) = 0x%04x\n", ntohs(tcp->check));
 
    if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("socket"); return 1; }
    if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) { perror("HDRINCL"); return 1; }
 
    to.sin_family = AF_INET;  to.sin_port = 0;  to.sin_addr.s_addr = ip->daddr;
    if (sendto(s, pkt, sizeof(pkt), 0, (struct sockaddr *)&to, sizeof(to)) < 0) {
        perror("sendto"); return 1;
    }
    puts("SYN 1๊ฐœ ์ „์†ก ์™„๋ฃŒ (127.0.0.2 -> 127.0.0.1:9, ๋ฃจํ”„๋ฐฑ ํ•œ์ •)");
    close(s);
    return 0;
}

๋ณด๋‚ธ ๋’ค tcpdump ๊ฐ€ ๋ญ๋ผ๊ณ  ํ•˜๋Š”์ง€ ๋ด์•ผ ํ•˜๋‹ˆ ๋‘˜์„ ๋ฌถ์€ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ•˜๋‚˜ ๋’€๋‹ค.

#!/usr/bin/env bash
# craft_demo.sh โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋กœ ์ฑ„์šด ์ฒดํฌ์„ฌ์„ ์ปค๋„/tcpdump ๊ฐ€ ์ธ์ •ํ•˜๋Š”์ง€ ๋ณธ๋‹ค.
# tcpdump -vv ๋Š” ์ฒดํฌ์„ฌ์„ ์Šค์Šค๋กœ ์žฌ๊ณ„์‚ฐํ•ด (correct)/(incorrect) ๋ฅผ ๋ถ™์—ฌ ์ค€๋‹ค.
set -uo pipefail
cd "$(dirname "$0")"
sudo -n tcpdump -i lo -c 1 -nvv 'tcp port 9' >craft_dump.txt 2>/dev/null &
TD=$!
sleep 1
sudo -n ./craft_send
wait $TD
echo "--- tcpdump ๊ฐ€ ๋ณธ ํŒจํ‚ท ---"
cat craft_dump.txt
gcc -O0 -g -Wall -o craft_send snippet.c craft_send.c; ./craft_demo.sh

craft demo.sh ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๊ฐ€ ๊ณ„์‚ฐํ•œ IP ์ฒดํฌ์„ฌ 0xbbee ์™€ TCP ์ฒดํฌ์„ฌ 0x6146 ์œผ๋กœ ์œ„์กฐ SYN ์„ ๋ณด๋ƒˆ๊ณ  tcpdump ๊ฐ€ cksum 0x6146 correct ๋กœ ํŒ์ •ํ–ˆ๋‹ค
craft demo.sh ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๊ฐ€ ๊ณ„์‚ฐํ•œ IP ์ฒดํฌ์„ฌ 0xbbee ์™€ TCP ์ฒดํฌ์„ฌ 0x6146 ์œผ๋กœ ์œ„์กฐ SYN ์„ ๋ณด๋ƒˆ๊ณ  tcpdump ๊ฐ€ cksum 0x6146 correct ๋กœ ํŒ์ •ํ–ˆ๋‹ค

cksum 0x6146 (correct) โ€” tcpdump ๊ฐ€ ์Šค์Šค๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด์„œ ๋งž๋‹ค๊ณ  ๋ถ™์ธ ํ‘œ์‹œ๋‹ค. ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๊ฐ€ ๊ณ„์‚ฐํ•œ ๊ฐ’์ด ํ”„๋กœํ† ์ฝœ ๊ทœ๊ฒฉ์— ๋งž๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์ œ3์˜ ๋„๊ตฌ๊ฐ€ ํ™•์ธํ•ด ์ค€ ์…ˆ์ด๋‹ค.

TCP ์ฒดํฌ์„ฌ์€ ํ—ค๋”๋งŒ์œผ๋กœ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ถœ๋ฐœ์ง€ยท๋ชฉ์ ์ง€ ์ฃผ์†Œ์™€ ํ”„๋กœํ† ์ฝœ ๋ฒˆํ˜ธ, ์„ธ๊ทธ๋จผํŠธ ๊ธธ์ด๋ฅผ ๋‹ด์€ 12๋ฐ”์ดํŠธ ์˜์‚ฌํ—ค๋”๋ฅผ ์•ž์— ๋ถ™์—ฌ์„œ ๊ฐ™์€ ํ•จ์ˆ˜์— ๋„ฃ๋Š”๋‹ค. craft_send.c ์˜ struct pseudo ๊ฐ€ ๊ทธ๊ฒƒ์ด๋‹ค.



๐Ÿ ํŒ์ •

๋„ค ๊ฐ€์ง€ ๊ทผ๊ฑฐ๋ฅผ ํ•œ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ฌถ์–ด ๋‘๋ฉด ๋‚˜์ค‘์— ํด๋”๋งŒ ์—ด์–ด๋„ ๊ฒฐ๋ก ์ด ์žฌํ˜„๋œ๋‹ค.

#!/usr/bin/env python3
"""solve.py โ€” 03.txt ๊ฐ€ ๋ฌด์Šจ ํ•จ์ˆ˜์ธ์ง€ ์‹ค์ธก์œผ๋กœ ํ™•์ •ํ•˜๊ณ  ์ •๋‹ต ํ•œ ๋‹จ์–ด๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
 
๋ฌธ์ œ๋Š” "๋ฌด์—‡์„ ํ•˜๋Š” ํ•จ์ˆ˜์ธ๊ฐ€"๋ฅผ ๋ฌป๋Š”๋‹ค. ๋ˆˆ์œผ๋กœ ๋ณด๊ณ  '์ฒดํฌ์„ฌ ๊ฐ™๋‹ค'๋กœ ๋๋‚ด์ง€ ์•Š๊ณ 
์•„๋ž˜ ๋„ค ๊ฐ€์ง€๋ฅผ ์‹ค์ œ๋กœ ๋Œ๋ ค์„œ ๊ฒฐ๋ก ์„ ๋‚ธ๋‹ค.
 
  [1] RFC 1071 ์ด ๋ฌธ์„œ์— ์ง์ ‘ ์ ์–ด ๋‘” ์˜ˆ์ œ์™€ ๋งž๋Š”๊ฐ€
  [2] ๊ต๊ณผ์„œ IP ํ—ค๋” ์˜ˆ์ œ์™€ ๋งž๋Š”๊ฐ€
  [3] tcpdump ๋กœ ์žก์€ ์ง„์งœ ํŒจํ‚ท์˜ IPยทICMP ์ฒดํฌ์„ฌ ์ž๋ฆฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌํ˜„ํ•˜๋Š”๊ฐ€
  [4] ๋ฌด์ž‘์œ„ ์ž…๋ ฅ 200๊ฐœ์—์„œ ๊ทœ๊ฒฉ ๊ตฌํ˜„๊ณผ ํ•œ ๋น„ํŠธ๋„ ์•ˆ ์–ด๊ธ‹๋‚˜๋Š”๊ฐ€ (์ง์ˆ˜ ๊ธธ์ด)
 
๋„ท ๋‹ค ํ†ต๊ณผํ•ด์•ผ ๋‹ต์„ ์ฐ๋Š”๋‹ค. ํ•˜๋‚˜๋ผ๋„ ์–ด๊ธ‹๋‚˜๋ฉด ์ด์œ ๋ฅผ ์ ๊ณ  ์ข…๋ฃŒ์ฝ”๋“œ 1 ๋กœ ๋๋‚ธ๋‹ค.
"""
import random
import struct
import subprocess
import sys
from pathlib import Path
 
HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
from reference import rfc1071, to_wire        # noqa: E402
 
BIN = HERE / "cksum"
PCAP = HERE / "live_icmp.pcap"
 
 
def build():
    subprocess.run(["gcc", "-O0", "-g", "-Wall", "-Wextra", "-o", str(BIN),
                    str(HERE / "snippet.c"), str(HERE / "driver.c")], check=True)
 
 
def snippet(raw: bytes) -> int:
    """์ปดํŒŒ์ผํ•œ ๋ฐฐํฌ๋ณธ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ์ „์„ (๋น…์—”๋””์–ธ) ์ˆœ์„œ๋กœ ๋ฐ”๊ฟ” ๋Œ๋ ค์ค€๋‹ค."""
    out = subprocess.run([str(BIN), raw.hex()], capture_output=True, text=True, check=True).stdout
    return to_wire(int(out.split("=")[-1], 16))
 
 
def pcap_packets(path: Path):
    blob = path.read_bytes()
    endian = "<" if blob[:4] in (b"\xd4\xc3\xb2\xa1", b"\x4d\x3c\xb2\xa1") else ">"
    linktype = struct.unpack(endian + "I", blob[20:24])[0]
    l2 = {0: 4, 1: 14, 113: 16, 101: 0}.get(linktype, 14)
    off = 24
    while off + 16 <= len(blob):
        _, _, caplen, _ = struct.unpack(endian + "IIII", blob[off:off + 16])
        yield blob[off + 16 + l2: off + 16 + caplen]
        off += 16 + caplen
 
 
ok = True
 
print("[1] RFC 1071 3์žฅ ์˜ˆ์ œ (00 01 f2 03 f4 f5 f6 f7)")
build()
got = snippet(bytes.fromhex("0001f203f4f5f6f7"))
print(f"    RFC ๋ฌธ์„œ๊ฐ€ ์ ์€ 1์˜ ๋ณด์ˆ˜ ํ•ฉ 0xddf2 -> ๊ทธ ๋ณด์ˆ˜ 0x220d ๊ฐ€ ์ฒดํฌ์„ฌ")
print(f"    ๋ฐฐํฌ๋ณธ=0x{got:04x}  ->", "์ผ์น˜" if got == 0x220D else "๋ถˆ์ผ์น˜")
ok &= got == 0x220D
 
print("[2] IP ํ—ค๋” ์˜ˆ์ œ (์ฒดํฌ์„ฌ ํ•„๋“œ๋ฅผ 0 ์œผ๋กœ ๋‘” 20๋ฐ”์ดํŠธ)")
hdr = bytes.fromhex("4500003c1c46400040060000ac100a63ac100a0c")
got = snippet(hdr)
print(f"    ๋ฐฐํฌ๋ณธ=0x{got:04x}  ๊ธฐ๋Œ€๊ฐ’=0xb1e6  ->", "์ผ์น˜" if got == 0xB1E6 else "๋ถˆ์ผ์น˜")
ok &= got == 0xB1E6
 
print(f"[3] ์‹ค์ œ๋กœ ์ „์„ ์„ ์ง€๋‚˜๊ฐ„ ํŒจํ‚ท ({PCAP.name})")
if not PCAP.exists():
    print("    pcap ์ด ์—†๋‹ค. ./capture_live.sh ๋ฅผ ๋จผ์ € ๋Œ๋ฆฐ๋‹ค.")
    ok = False
else:
    n = miss = 0
    for ip in pcap_packets(PCAP):
        if not ip or ip[0] >> 4 != 4:
            continue
        ihl = (ip[0] & 0xF) * 4
        hdr, payload = ip[:ihl], ip[ihl:]
        n += 1
        if snippet(hdr[:10] + b"\x00\x00" + hdr[12:]) != struct.unpack("!H", hdr[10:12])[0]:
            miss += 1
        if hdr[9] == 1 and len(payload) >= 4:
            n += 1
            if snippet(payload[:2] + b"\x00\x00" + payload[4:]) != struct.unpack("!H", payload[2:4])[0]:
                miss += 1
    print(f"    ์ฒดํฌ์„ฌ ์ž๋ฆฌ {n}๊ณณ ์ค‘ {n - miss}๊ณณ ์žฌํ˜„, ์–ด๊ธ‹๋‚œ ๊ณณ {miss}")
    ok &= n > 0 and miss == 0
 
print("[4] ๋ฌด์ž‘์œ„ ์ง์ˆ˜ ๊ธธ์ด 200๊ฐœ โ€” ๊ทœ๊ฒฉ ๊ตฌํ˜„๊ณผ ์ „์ˆ˜ ๋Œ€์กฐ")
random.seed(1071)
miss = 0
for _ in range(200):
    raw = bytes(random.randrange(256) for _ in range(random.randrange(1, 300) * 2))
    if snippet(raw) != rfc1071(raw):
        miss += 1
print(f"    ๋ถˆ์ผ์น˜ {miss} / 200")
ok &= miss == 0
 
print()
if ok:
    print("๊ฒฐ๋ก : 03.txt ๋Š” RFC 1071 ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ(in_cksum) ์ด๋‹ค.")
    print("      IP_HDRINCL ๋กœ์šฐ์†Œ์ผ“์œผ๋กœ ํ—ค๋”๋ฅผ ์ง์ ‘ ๋งŒ๋“œ๋Š” ์ฝ”๋“œ๊ฐ€ ์ปค๋„ ๋Œ€์‹  ์ฑ„์›Œ์•ผ ํ•˜๋Š” ๊ฐ’์ด๋‹ค.")
    print()
    print("FLAG: checksum")
else:
    print("๊ฒฐ๋ก  ๋ณด๋ฅ˜ โ€” ์œ„์—์„œ ์–ด๊ธ‹๋‚œ ํ•ญ๋ชฉ์„ ๋จผ์ € ํ™•์ธํ•  ๊ฒƒ")
    sys.exit(1)
python3 solve.py

solve.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” RFC 1071 ์˜ˆ์ œ์™€ IP ํ—ค๋” ์˜ˆ์ œ๊ฐ€ ์ผ์น˜ํ•˜๊ณ  ์‹ค์ œ ํŒจํ‚ท 12๊ณณ์ด ์ „๋ถ€ ์žฌํ˜„๋˜๋ฉฐ ๋ฌด์ž‘์œ„ 200๊ฐœ๋„ ๋ถˆ์ผ์น˜ 0์œผ๋กœ ํ†ต๊ณผํ•ด FLAG checksum ์„ ์ถœ๋ ฅํ•œ๋‹ค
solve.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” RFC 1071 ์˜ˆ์ œ์™€ IP ํ—ค๋” ์˜ˆ์ œ๊ฐ€ ์ผ์น˜ํ•˜๊ณ  ์‹ค์ œ ํŒจํ‚ท 12๊ณณ์ด ์ „๋ถ€ ์žฌํ˜„๋˜๋ฉฐ ๋ฌด์ž‘์œ„ 200๊ฐœ๋„ ๋ถˆ์ผ์น˜ 0์œผ๋กœ ํ†ต๊ณผํ•ด FLAG checksum ์„ ์ถœ๋ ฅํ•œ๋‹ค

์ •๋‹ต์€ checksum. CodeEngn ๋ฌธ์ œ๋ผ DH ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ž˜ํผ๋Š” ์—†๊ณ  ์†Œ๋ฌธ์ž ํ•œ ๋‹จ์–ด๋ฅผ ๊ทธ๋Œ€๋กœ ์ œ์ถœํ•œ๋‹ค.

crc ๋ฅผ ๋– ์˜ฌ๋ ธ๋‹ค๋ฉด ๋ฐฉํ–ฅ์ด ๋‹ค๋ฅด๋‹ค. CRC ๋Š” ๋‹คํ•ญ์‹ ๋‚˜๋ˆ—์…ˆ์ด๊ณ , ์ด ์ฝ”๋“œ์—๋Š” ๋‚˜๋ˆ—์…ˆ๋„ ์‹œํ”„ํŠธ ๋ ˆ์ง€์Šคํ„ฐ๋„ ์—†๋‹ค. ์—ฌ๊ธฐ ์žˆ๋Š” ๊ฑด ๋ง์…ˆ๊ณผ ๋ณด์ˆ˜๋ฟ์ด๋‹ค.


๐Ÿ“ ๊ฒฐ๋ก 

๋ชจ์–‘์ด ๊ฐ™๋‹ค๊ณ  ๊ฐ™์€ ๋ฌผ๊ฑด์€ ์•„๋‹ˆ๋‹ค.

"1์˜ ๋ณด์ˆ˜ ํ•ฉ์— ๋ณด์ˆ˜" ๋ผ๋Š” ํ˜•ํƒœ๋งŒ ๋ณด๊ณ ๋„ ๋‹ต์€ ์ฐ์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๊ฑด ๋‹ต์„ ๋งžํžˆ๋Š” ๊ฒƒ์ด์ง€ ํ™•์ •ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋‹ค. ๋ฐฐํฌ๋ณธ์„ ๊ทธ๋Œ€๋กœ ์ปดํŒŒ์ผํ•ด ์‹ค์ œ ํŒจํ‚ท์˜ ์ฒดํฌ์„ฌ ์ž๋ฆฌ 12๊ณณ๊ณผ ๋งž์ถฐ ๋ณด๊ณ  ๋‚˜์„œ์•ผ ๊ทผ๊ฑฐ๊ฐ€ ์ƒ๊ฒผ๋‹ค. ์ฝ”๋“œ ์กฐ๊ฐ ํ•˜๋‚˜๋ฅผ ๋ฐ›์•˜์„ ๋•Œ ๊ฐ€์žฅ ๋น ๋ฅธ ํ™•์ธ ์ˆ˜๋‹จ์€ ๋Œ€์ฒด๋กœ "๊ทธ๋Œ€๋กœ ๋Œ๋ ค ๋ณด๋Š” ๊ฒƒ"์ด๋‹ค.

๋ฐ”์ดํŠธ ์ˆœ์„œ๋ฅผ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹ˆ๋ผ ์ €์žฅ ์‹œ์ ์—์„œ ๋ด์•ผ ํ•œ๋‹ค.

0x0d22 ์™€ 220d ๋ฅผ ๋ณด๊ณ  ์ฒ˜์Œ์—” ๋ถˆ์ผ์น˜๋กœ ํŒ๋‹จํ–ˆ๋‹ค. ํ™”๋ฉด์— ์ฐํžŒ 16์ง„์ˆ˜๋Š” ์ˆ˜์น˜์ผ ๋ฟ์ด๊ณ , ์ „์„ ์— ๋‚˜๊ฐ€๋Š” ๊ฒƒ์€ ๊ทธ ์ˆ˜์น˜๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์ผ์„ ๋•Œ์˜ ๋ฐ”์ดํŠธ๋‹ค. ํ˜ธ์ŠคํŠธ ์ˆœ์„œ๋กœ ๋”ํ•ด์„œ ๊ทธ๋Œ€๋กœ ์ €์žฅํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๋งž๋Š”๋‹ค๋Š” ๊ฒŒ ์ธํ„ฐ๋„ท ์ฒดํฌ์„ฌ์˜ ์„ค๊ณ„ ์˜๋„์ด๊ธฐ๋„ ํ•˜๋‹ค.

์ดˆ๊ธฐํ™” ๋ˆ„๋ฝ์€ ์šฐ์—ฐํžˆ ๋งž์„ ์ˆ˜ ์žˆ์–ด์„œ ๋” ์œ„ํ—˜ํ•˜๋‹ค.

-O0 ๋นŒ๋“œ๋Š” ๊ฒฝ๊ณ ๋„ ์—†์ด ์ •๋‹ต์„ ๋ƒˆ๋‹ค. rbx ์— ๋งˆ์นจ 0์ด ๋“ค์–ด ์žˆ์—ˆ์„ ๋ฟ์ด๋‹ค. ํ˜ธ์ถœ ๊ฒฝ๋กœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์กฐ์šฉํžˆ ํ‹€๋ฆฐ ๊ฐ’์„ ๋‚ด๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค. ์ƒˆ ์ฝ”๋“œ์— -Wall -Wextra ๋งŒ ๊ฑธ์–ด ๋†“๊ณ  ์•ˆ์‹ฌํ•˜์ง€ ๋ง๊ณ  ์ตœ์ ํ™”๋ฅผ ์ผ  ๋นŒ๋“œ๋„ ํ•œ ๋ฒˆ์€ ๋Œ๋ ค ๋ณด๋Š” ๊ฒŒ ๋‚ซ๋‹ค.

๋ฐฉ์–ด ๊ด€์ ์—์„œ ์ด ํ•จ์ˆ˜๋Š” ์ข‹์€ ํƒ์ง€ ์ง€ํ‘œ๋‹ค.

์ผ๋ฐ˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์ฒดํฌ์„ฌ์„ ์ง์ ‘ ๊ณ„์‚ฐํ•  ์ผ์ด ์—†๋‹ค. ์ปค๋„์ด ํ•ด ์ค€๋‹ค. ์‚ฌ์šฉ์ž ์˜์—ญ ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ RFC 1071 ํ˜•ํƒœ์˜ ๋ฃจํ‹ด์ด ๋ฐœ๊ฒฌ๋˜๊ณ  ๊ทธ ์˜†์— SOCK_RAW ์™€ IP_HDRINCL ์ด ๊ฐ™์ด ์žˆ๋‹ค๋ฉด, ๊ทธ๊ฑด ์ถœ๋ฐœ์ง€๋ฅผ ์œ„์กฐํ•œ ํŒจํ‚ท์„ ๋งŒ๋“ค๊ฒ ๋‹ค๋Š” ๋œป์ด๋‹ค. ๋„คํŠธ์›Œํฌ ์ชฝ์—์„œ๋Š” ๊ฒฝ๊ณ„์—์„œ uRPF ๋‚˜ BCP 38 ๊ณ„์—ด์˜ ์ถœ๋ฐœ์ง€ ์ฃผ์†Œ ํ•„ํ„ฐ๋ง์„ ์ผœ ๋‘๋ฉด ์œ„์กฐ๋œ ์ถœ๋ฐœ์ง€ ํŒจํ‚ท์ด ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

๊ฐ™์€ ํ˜•ํƒœ์˜ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋“œ์‹œ ๊ทœ๊ฒฉ๋Œ€๋กœ์ธ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

์ด ๋ฐœ์ทŒ๋ณธ์€ ํ™€์ˆ˜ ๊ธธ์ด์—์„œ ๋ฉ”์‹œ์ง€ ๋ฐ– 1๋ฐ”์ดํŠธ๋ฅผ ์ฝ๊ณ , 6๋ฐ”์ดํŠธ ์ž…๋ ฅ์—์„œ ์ด๋ฏธ ์บ๋ฆฌ ํ•˜๋‚˜๋ฅผ ํ˜๋ฆฐ๋‹ค. ์ธํ„ฐ๋„ท์— ๊ตด๋Ÿฌ๋‹ค๋‹ˆ๋Š” ์ฒดํฌ์„ฌ ์Šค๋‹ˆํŽซ์„ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด ์“ธ ๋•Œ ํ”ํžˆ ๋”ฐ๋ผ์˜ค๋Š” ๋ฌธ์ œ๋‹ค. ์žฌ๊ตฌํ˜„ํ•˜๊ธฐ ์ „์— ๊ทœ๊ฒฉ ๋ฌธ์„œ์˜ ์˜ˆ์ œ ๋ฒกํ„ฐ๋กœ ํ•œ ๋ฒˆ ์žฌ ๋ณด๋ฉด ๋Œ€๋ถ€๋ถ„ ์ด ์ž๋ฆฌ์—์„œ ๊ฑธ๋ฆฐ๋‹ค.



์ด ๊ธ€์ด ๋„์›€์ด ๋๋‚˜์š”?

Comments

๋Œ“๊ธ€

0๊ฐœ

๋Œ“๊ธ€์„ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ด์š”. (๋„ค์ด๋ฒ„ ยท ๊ตฌ๊ธ€ ๊ณ„์ •)

๋Œ“๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅ‰ Bronze 1] 31์ค„ ๋ฐœ์ทŒ๋ณธ์ด base64 ์ธ์ฝ”๋”๋ผ๋Š” ๊ฑธ ์ฆ๋ช…ํ•˜๊ธฐ โ€” DreamHack [CodeEngn] Malware L05 ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 1] 31์ค„ ๋ฐœ์ทŒ๋ณธ์ด base64 ์ธ์ฝ”๋”๋ผ๋Š” ๊ฑธ ์ฆ๋ช…ํ•˜๊ธฐ โ€” DreamHack [CodeEngn] Malware L05 ํ’€์ด

์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค 31์ค„๋งŒ ์ฃผ๊ณ  "๋ฌด์—‡์„ ํ•˜๋Š” ํ•จ์ˆ˜์ธ๊ฐ€"๋ฅผ ๋ฌป๋Š”๋‹ค. ํ‘œ์ค€ ์•ŒํŒŒ๋ฒณ 64์ž์™€ 6๋น„ํŠธ ๋งˆ์Šคํฌ๊ฐ€ ๋ณด์ด๋‹ˆ base64 ๊ฐ™์€๋ฐ, ๋ˆˆ์œผ๋กœ ์ฐ๋Š” ๋Œ€์‹  ๊ฐ€๋ ค์ง„ ๋‘ ์ค„์„ ์ฑ„์›Œ ์ปดํŒŒ์ผํ•˜๊ณ  ์ž…๋ ฅ 304์ข…์„ ํ‘œ์ค€๊ณผ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ๋งž์ถฐ ๋ดค๋‹ค. ๋ค์œผ๋กœ ์ด ๊ตฌํ˜„์ด 3์˜ ๋ฐฐ์ˆ˜ ์•„๋‹Œ ๊ธธ์ด์—์„œ ํ„ฐ์ง€๊ณ  76์—ด ๊ทœ๊ฒฉ๋„ ์–ด๊ธด๋‹ค๋Š” ๊ฒƒ๊นŒ์ง€ ์‹ค์ธกํ–ˆ๋‹ค.
#dreamhack#ctf#misc+6
2026-08-19#dreamhack +4
[๐Ÿฅ‰ Bronze 1] ์ •๋‹ต์€ ์˜ˆ์‹œ ์•ˆ์— ์žˆ์—ˆ๋‹ค โ€” DreamHack [CodeEngn] Malware L01 ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 1] ์ •๋‹ต์€ ์˜ˆ์‹œ ์•ˆ์— ์žˆ์—ˆ๋‹ค โ€” DreamHack [CodeEngn] Malware L01 ํ’€์ด

์•…์„ฑ์ฝ”๋“œ ์†Œ์Šค ์ฝ”๋“œ ์กฐ๊ฐ ํ•˜๋‚˜๋งŒ ๋˜์ ธ์ฃผ๊ณ  "์ด๊ฒƒ์˜ ๊ณต๊ฒฉ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ธ๊ฐ€"๋ฅผ ๋ฌป๋Š” ๋ฌธ์ œ. ์ฝ”๋“œ๋ฅผ ๋œฏ์–ด๋ณด๋ฉด SYN ํ”Œ๋ž˜๊ทธ๋ฅผ ๊ณ ์ •ํ•˜๊ณ  ์ถœ๋ฐœ์ง€ IP๋ฅผ ๋งค ํŒจํ‚ท ๋žœ๋ค์œผ๋กœ ๋ฐ”๊พธ๋ฉฐ ACK ์—†์ด ์˜์›ํžˆ ์˜๋Š”, ๊ต๊ณผ์„œ์ ์ธ SYN Flood๋‹ค. ๋” ์ •ํ™•ํ•œ ์šฉ์–ด๋กœ ๋‹ต์„ ๋ƒˆ๋‹ค๊ฐ€ ๋‘ ๋ฒˆ ์˜ค๋‹ต์„ ๋จน๊ณ  ๋‚˜์„œ์•ผ, ๋ฌธ์ œ๊ฐ€ ์ค€ ์˜ˆ์‹œ ๋ฌธ๊ตฌ ์ž์ฒด๊ฐ€ ์ •๋‹ต์ด์—ˆ๋‹ค๋Š” ๊ฑธ ๊นจ๋‹ฌ์•˜๋‹ค.
#dreamhack#ctf#misc+3
2026-07-20#dreamhack +4
[๐Ÿฅˆ Bronze 2] ํ•จ์ˆ˜ ์ฃผ์†Œ์ผ๊นŒ, ํ˜ธ์ถœ ์ง€์ ์ผ๊นŒ โ€” DreamHack [CodeEngn] Malware L08 ํ’€์ด
blog

[๐Ÿฅˆ Bronze 2] ํ•จ์ˆ˜ ์ฃผ์†Œ์ผ๊นŒ, ํ˜ธ์ถœ ์ง€์ ์ผ๊นŒ โ€” DreamHack [CodeEngn] Malware L08 ํ’€์ด

๋‹ค๋ฅธ ์•…์„ฑ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด ์ถ”๊ฐ€ ๊ฐ์—ผ์„ ์ผ์œผํ‚ค๋Š” ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ์ฐพ์œผ๋ผ๋Š” ๋ฌธ์ œ. ๊ทธ๋ž˜ํ”„ ์ „์ฒด๊ฐ€ ShellExecuteExA๋กœ ๋Œ€์ƒ ํŒŒ์ผ์„ ์‹คํ–‰ํ•˜๋Š” ํ•˜๋‚˜์˜ ํ•จ์ˆ˜์ธ๋ฐ, ๊ทธ ํ•จ์ˆ˜ ์ž์ฒด์˜ ์‹œ์ž‘ ์ฃผ์†Œ๋ฅผ ๋ƒˆ๋‹ค๊ฐ€ ์˜ค๋‹ต์„ ๋ฐ›์•˜๋‹ค. ํ•จ์ˆ˜ ์•ˆ์— ShellExecuteExA ํ˜ธ์ถœ์ด ๋‘ ๊ณณ์ด๋ผ๋Š” ๊ฑธ ์•Œ๊ณ ๋„ ์–ด๋А ์ชฝ์ธ์ง€ ํ—ท๊ฐˆ๋ ธ๋Š”๋ฐ, ๊ฒฐ๊ตญ "ํ•จ์ˆ˜์˜ ์ฃผ์†Œ"๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฑด ์‹คํ–‰ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ทธ ์ง€์ ์ด์—ˆ๋‹ค.
#dreamhack#ctf#reversing+5
2026-07-19#dreamhack +4