AlpacaHack Round 8 (Rev)ã¸åå ãã¾ããããã®write-upè¨äºã§ãã
IDAã®è§£æçµæãã¡ã¤ã«.i64ãªã©ããGitHubã§å ¬éãã¦ãã¾ãã
- ã³ã³ãã¹ãæ¦è¦
- çµæ
- ç°å¢
- 解ããåé¡
- ææ³
ã³ã³ãã¹ãæ¦è¦
2024/12/30(æ) 12:00 +09:00 - 12/30(æ) 18:00 +09:00
ã®6æééå¬ã§ãããä»ã«ã¼ã«ã¯ã³ã³ãã¹ããã¼ã¸ããå¼ç¨ãã¾ã:
AlpacaHack Round 8 (Rev) ã¸ããããï¼ AlpacaHack ã¯å人æ¦ã® CTF ãç¶ç¶ãã¦éå¬ããæ°ãããã©ãããã©ã¼ã ã§ãã AlpacaHack Round 8 㯠AlpacaHack ã§è¡ããã 8 åç®ã® CTF ã§ãRev ã«ãã´ãªãã 4 åãåºé¡ããã¾ãã å¹ åºãé£æ度ã®åé¡ãåºé¡ããããããåå¿è ãå«ãæ§ã ãªã¬ãã«ã®æ¹ã«æ¥½ããã§ããã ããããã«ãªã£ã¦ãã¾ãã åé¡ä½æè 㯠arata-nvm 㨠sugi ã§ãï¼ åå æ¹æ³ 1. å³ä¸ã®ãSign Upããã¿ã³ãã AlpacaHack ã®ã¦ã¼ã¶ã¼ç»é²ããã¦ãã ããã 2. ç»é²å®äºå¾ããã®ãã¼ã¸ã®ãRegisterããã¿ã³ãæ¼ã㦠CTF ã®åå ç»é²ããã¦ãã ããã 注æäºé - AlpacaHack ã¯å人æ¦ã®CTFãã©ãããã©ã¼ã ã§ããããããã¼ã ã§ã®ç»é²ã¯ç¦æ¢ãã¦ãã¾ãã - åé¡ã¯éå¶ãæ³å®ããé£æ度ã®é ã«ä¸¦ãã§ãã¾ãã - åé¡ã®é ç¹ã¯è§£ãã人æ°ã«å¿ãã¦å¤åãã¾ãã - ãã©ã°ãã©ã¼ããã㯠Alpaca{...} ã§ãã - å ¨ã¦ã®ã¢ãã¦ã³ã¹ã¯ AlpacaHack ã® Discord ãµã¼ãã¼ ã§è¡ããã¾ãã - ã¢ãã¦ã³ã¹ã¯æ¬ãµã¼ãã¹ä¸ã§ãè¡ããã¨ãããã¾ãããDiscord ãµã¼ãã¼ã主ãªé£çµ¡æ段ã¨ãªãã¾ãã - åé¡ãçºçããå ´åã#ticket ãã£ã³ãã«ããé£çµ¡ãã¦ãã ããããã ããåé¡ã®ãã³ãã¯æä¾ãã¾ããã - 競æã·ã¹ãã èªä½ã¸ã®æ»æã¯è¡ããªãã§ãã ããããªããå¶ç¶çºè¦ãããã°ã®å ±åã¯æè¿ãã¾ãã
ããã¾ã§ã®Roundåæ§ã«åé¡ã¯éå¶ãæ³å®ããé£æ度ã®é ã«ä¸¦ãã§ãã¾ã
ã¨æè¨ããã¦ããã並ã³é ã§æ³å®é£æ度ã示ããã¾ããã
çµæ
æ£ã®å¾ç¹ãå¾ã¦ãã62人ä¸ã620ç¹ã§8ä½ã§ãã:
ã¾ããCertificateç®æããé ä½ã®è¨¼ææ¸ã表示ã§ãã¾ã:
ç°å¢
Windowsã®WSL2(Ubuntu 24.04)ã使ã£ã¦åãçµã¿ã¾ããã
Windows
c:\>ver Microsoft Windows [Version 10.0.19045.5247] c:\>wsl -l -v NAME STATE VERSION * Ubuntu-24.04 Running 2 docker-desktop-data Running 2 kali-linux Stopped 2 docker-desktop Running 2 Ubuntu-22.04 Running 2 c:\>
ä»ã½ãã
- IDA Free Version 9.0.241217 Windows x64 (64-bit address size)(FreeçIDAã§ãversion 7é ããx64ãã¤ããªããversion 8.2ããã¯x86ãã¤ããªãã¯ã©ã¦ããã¼ã¹ã®éã³ã³ãã¤ã«ãã§ãã¾ã)
WSL2(Ubuntu 24.04)
$ cat /proc/version Linux version 5.15.167.4-microsoft-standard-WSL2 (root@f9c826d3017f) (gcc (GCC) 11.2.0, GNU ld (GNU Binutils) 2.37) #1 SMP Tue Nov 5 00:21:55 UTC 2024 $ cat /etc/os-release PRETTY_NAME="Ubuntu 24.04.1 LTS" NAME="Ubuntu" VERSION_ID="24.04" VERSION="24.04.1 LTS (Noble Numbat)" VERSION_CODENAME=noble ID=ubuntu ID_LIKE=debian HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" UBUNTU_CODENAME=noble LOGO=ubuntu-logo $ python3 --version Python 3.12.3 $ python3 -m pip show pip | grep Version: Version: 24.0 $ python3 -m pip show IPython | grep Version: Version: 8.24.0 $ python3 -m pip show pwntools | grep Version: Version: 4.13.1 $ python3 -m pip show z3-solver | grep Version: Version: 4.8.16.0 $ gdb --version GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git Copyright (C) 2024 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ gdb --batch --eval-command 'version' | grep 'Pwndbg:' Pwndbg: 2024.02.14 build: 2b9beef $
解ããåé¡
[Rev] masking tape (61 solves, 124 points)
Masking tape is also useful for flag checking :)
é
å¸ãã¡ã¤ã«ã¨ãã¦ãmasking-tape
ãããã¾ãã:
$ file * masking-tape: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=61a9c2ab285b526528b77f1170889a951fb7efe2, for GNU/Linux 3.2.0, not stripped $
IDAã§éãã¦éã³ã³ãã¤ã«ãã¾ãããå¤æ°åçã調æ´ããçµæã§ã:
int __fastcall main(int argc, const char **argv) { size_t i; // [rsp+18h] [rbp-28h] char *pInput; // [rsp+20h] [rbp-20h] size_t dwInputSize; // [rsp+28h] [rbp-18h] char *pAllocated1; // [rsp+30h] [rbp-10h] char *pAllocated2; // [rsp+38h] [rbp-8h] if ( argc == 2 ) { pInput = (char *)argv[1]; dwInputSize = strlen(pInput) + 1; pAllocated1 = (char *)malloc(dwInputSize); pAllocated2 = (char *)malloc(dwInputSize); for ( i = 0LL; i < dwInputSize; ++i ) { pInput[i] = (pInput[i] >> 5) | (8 * pInput[i]); if ( (pInput[i] & 1) != 0 ) { pAllocated1[i] = pInput[i] & 0x33; pAllocated2[i] = pInput[i] & 0xCC; } else { pAllocated1[i] = pInput[i] & 0xCC; pAllocated2[i] = pInput[i] & 0x33; } } if ( !strcmp(enc1, pAllocated1) && !strcmp(&enc2, pAllocated2) ) puts("congratz"); else puts("wrong"); return 0; } else { printf("usage: %s <input>\n", *argv); return 0; } }
å
¥å1æåãã¨ã«(pInput[i] >> 5) | (8 * pInput[i])
ã®å¤æãæ½ããå¤æçµæã®æä¸ä½ãããã«å¾ã£ã¦çµæã2ã¤ã®é
åã¸æ ¼ç´ãã¦ãã¾ãã(0x33 ^ 0xCC) == 0xFF
ã§ãããããå¤æçµæã®åããããã¹ã¦ããã©ã¡ããã®é
åã¸ã®ã¿ã«å
¥ãã¾ãã
æçµçã«ã2ã¤ã®ã°ãã¼ãã«å¤æ°é
åenc1
ã¨enc2
ã使ã£ã¦æ£èª¤ãå¤å®ãã¦ãã¾ããenc1
ã¨enc2
ã®å
容ãããæ£è§£ã¨ãªãå
¥åãã©ã°ãéç®ããã½ã«ãã¼ãæ¸ãã¾ãã:
#!/usr/bin/env python3 # fmt: off # IDAã®0x2020ä»è¿ã¸ãã¦ã¹ã«ã¼ã½ã«ãåããã¦ç¯å²é¸æããShift+Eã§ãExport dataããã¦Hex表ç¾ãã¤ãåãå¾ã¾ãã enc1 = bytes.fromhex("08 23 03 03 13 03 13 03 01 23 31 13 11 C8 03 C8 03 13 01 C8 13 13 03 13 13 11 13 23 00") enc2 = bytes.fromhex("02 40 80 08 08 08 C8 C8 80 88 08 80 88 32 08 32 80 80 80 32 08 80 08 08 48 88 80 C8 00") # fmt: on flag = "" for i in range(len(enc1)): v1 = enc1[i] v2 = enc2[i] if ((v1 & 0xCC) == 0) and ((v2 & 0x33) == 0): v = (v1 & 0x33) | (v2 & 0xCC) elif ((v1 & 0x33) == 0) and ((v2 & 0xCC) == 0): v = (v1 & 0xCC) | (v2 & 0x33) else: raise Exception("") v = ((v << 5) & 0xFF) | ((v >> 3) & 0b11111) flag += chr(v) print(flag.strip("\x00"))
å®è¡ãã¾ãã:
$ ./solve.py Alpaca{y0u'r3_a_pr0_crack3r} $ ./masking-tape "Alpaca{y0u'r3_a_pr0_crack3r}" congratz $
ãã©ã°ãå
¥æã§ãã¾ãã: Alpaca{y0u'r3_a_pr0_crack3r}
ãªããã³ã³ãã¹ãä¸ã§ã¯ãããç©ãåãéã®æ°å¤ãééãã¦ãã¦ãæ°åãã¹ãã¦ãã¾ããâ¦â¦ã
[Rev] hidden (23 solves, 192 points)
How do I hide from a decompiler?
æ¬åé¡ãã¤ããªãIDAã§è§£æãããã¡ã¤ã«hidden.i64ãå ¬éãã¦ãã¾ãã
é
å¸ãã¡ã¤ã«ã¨ãã¦ãhidden
ãããã¾ãã:
$ file * hidden: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1cee3c62169c309aaf0c2c2f7885bd36ca87f6e8, for GNU/Linux 3.2.0, stripped $
åé¡æãããã¦ä½ããä»è¾¼ã¾ãã¦ããé°å²æ°ãæãã¤ã¤ããIDAã§éãã¦éã³ã³ãã¤ã«ãã¾ããã
main
é¢æ°ã¯æ¬¡ã®å
容ã§ãã(å¤æ°åçãªãã¼ã å¾):
__int64 __fastcall main(int argc, char **argv) { unsigned __int64 i; // [rsp+18h] [rbp-58h] char *pStrInput; // [rsp+20h] [rbp-50h] size_t dwStrInputLength; // [rsp+28h] [rbp-48h] _DWORD *pdwArrayInOut; // [rsp+38h] [rbp-38h] char strAlpacaHackRound8[24]; // [rsp+40h] [rbp-30h] BYREF unsigned __int64 qwCanary; // [rsp+58h] [rbp-18h] qwCanary = __readfsqword(0x28u); strcpy(strAlpacaHackRound8, "AlpacaHackRound8"); if ( argc > 1 ) { pStrInput = argv[1]; dwStrInputLength = strlen(pStrInput); pdwArrayInOut = calloc((dwStrInputLength + 3) >> 2, 4uLL); memcpy(pdwArrayInOut, pStrInput, dwStrInputLength); for ( i = 0LL; i < (dwStrInputLength + 3) >> 2; ++i ) pdwArrayInOut[i] = ProcConvert(pdwArrayInOut[i], strAlpacaHackRound8); if ( !memcmp(pdwArrayInOut, dword_4040, 4 * g_qwValue_Constant27) ) puts("congratz"); else puts("wrong"); return 0LL; } else { printf("usage: %s <input>\n", *argv); return 0LL; } }
ä¸è¨ã³ã¼ãã§ProcConvert
ã¨åä»ãã¦ããé¢æ°ã¯ã0x1272
ã«ããé¢æ°ã§ãããã®é¢æ°ã®èªè§£ãæ¬åé¡ã®ä¸»é¡ã§ããã
æ½ããã¦ããèéã³ã³ãã¤ã«ææ³
(ã¨ããã§ãAnti-decompileãã®å訳表è¨ã¯ãã¢ã³ããã³ã³ãã¤ã«ãã¨ã«ã¿ã«ã表è¨ãå¤ãå°è±¡ã§ãããã å人çã«ã¯ããã³ã³ãã¤ã«ã表è¨ã ã¨ããããè¦éããããããªã®ã§ããéã³ã³ãã¤ã«ããç¨ããèªå¥ã使ãããã§ãããã®ãããèéã³ã³ãã¤ã«ã表è¨ã¨ãã¦ãã¾ãã)
0x1272
ã®é¢æ°ã§ã®éã³ã³ãã¤ã«çµæã¯æ¬¡ã®ãã®ã§ãã(å¤æ°åçã¯ãªãã¼ã æ¸ã¿ã§ã):
unsigned int __fastcall ProcConvert(unsigned int dwInputPart, _DWORD *pdwInOutArraySize4) { ProcSome_1(__ROL4__(*pdwInOutArraySize4, 5) + __ROR4__(pdwInOutArraySize4[1], 3)); ProcSome_2(__ROR4__(pdwInOutArraySize4[2], 3) - __ROL4__(pdwInOutArraySize4[3], 5)); ProcSome_3(dwInputPart); *pdwInOutArraySize4 ^= __ROR4__(0, 13); pdwInOutArraySize4[1] ^= __ROR4__(0, 15); pdwInOutArraySize4[2] ^= __ROL4__(0, 13); pdwInOutArraySize4[3] ^= __ROL4__(0, 11); return 0; }
ãããéã¢ã»ã³ãã«ç»é¢ã¨è¦æ¯ã¹ãã¨ãéã³ã³ãã¤ã«çµæã«ã¯ä½ãã¨æ¬ è½ãã¦ããããããã¨ãåããã¾ããè¦ã¤ããããããæ¹æ³ã¨ãã¦ãIDA View-A
ã¨Pseudocode-A
ã¦ã£ã³ãã¦ã横ã«ä¸¦ã¹ãPseudocode-A
ã¦ã£ã³ãã¦å
é¨ã§å³ã¯ãªãã¯ãã¦è¡¨ç¤ºãããã³ã³ããã¹ãã¡ãã¥ã¼ã§Synchronize with
âIDA View-A Hex-View-1
ãé¸æããæ¹æ³ãããã¾ããããããã¨ãéã³ã³ãã¤ã«ã¦ã£ã³ãã¦ã§é¸æä¸ã®è¡ã«å¯¾å¿ããã¢ã»ã³ããªå½ä»¤ããéã¢ã»ã³ãã«ã¦ã£ã³ãã¦å´ã§ãç·è²ã«åæããã¦è¡¨ç¤ºããã¾ã:
éã¢ã»ã³ãã«ç»é¢ã¨éã³ã³ãã¤ã«ç»é¢ãè¦æ¯ã¹ã¦ã¿ãã¨ãéã¢ã»ã³ãã«ç»é¢ã§ã¯ç»å ´ãã次ã®å 容ããéã³ã³ãã¤ã«ç»é¢ã«ã¯ç»å ´ããªããã¨ãåããã¾ãã:
0x12EF
ã§ã®callæã®ç¬¬1å¼æ°ã¨ãã¦ãéã¢ã»ã³ãã«ç»é¢ã§ã¯[rbp+0x14]
ã[rbp+0xC]
ã[rbp+0x8]
ã®3åã®å¤ã®XORçµæã渡ãã¦ãã¾ãããããéã³ã³ãã¤ã«ç»é¢ã§ã¯åç´ã«[rbp+0x14]
ã®1åã®å¤ã渡ãã¦ããã ãã§ãã0x12F7
ä»è¿ã§ãéã¢ã»ã³ãã«ç»é¢ã§ã¯mov eax, [rbp+0x4]
ãand eax, 1
ãtest eax, eax
ãjz short loc_136E
ã®æ¡ä»¶åå²ãåå¨ãã¾ãããããéã³ã³ãã¤ã«ç»é¢ã§ã¯æ¡ä»¶åå²ãåå¨ãã¾ããã常æã¸ã£ã³ããããã®ã¨ãã¦è¡¨ç¤ºããã¦ãã¾ãã- ã¸ã£ã³ãå
ã®
0x1377
çã«ã¤ãã¦ãéã³ã³ãã¤ã«ç»é¢ã§ã¯mov eax, [rbp+0x8]
ãror eax, 0Dh
çããã¼ã«ã«å¤æ°ã®å¤ã«åºã¥ãã¦RotateRightãã¦ãã¾ãããããéã³ã³ãã¤ã«ç»é¢ã§ã¯__ROR4__(0, 13)
çã¨ãRotateRightãã第1ãªãã©ã³ãã0
åºå®ã«ãªã£ã¦ãã¾ãã
ã©ãããã次ã®èéã³ã³ãã¤ã«ææ³ãæ½ããã¦ããããã§ã:
0x1272
ã®é¢æ°å é¨ã ããè¦ãã¨ã[rbp+0xC]
ã[rbp+0x8]
ã[rbp+0x4]
ã®3åã®å¤ã¯ãé¢æ°åé ã§0
åæåãã¦ããã ãã§ã以éå¤åããªãããã«è¦ãã¾ãã- ãããå®éã¯ãéä¸ã§callãã¦ãã
0x124F
ã0x122C
ã0x1209
ã®é¢æ°ãã0x1272
é¢æ°ä¸ã®ãã¼ã«ã«å¤æ°ãç´æ¥æ¸ãæãã¦ãã¾ããéã³ã³ãã¤ã©ã¯ãã®æ¸ãæããèªèã§ãã¦ãã¾ããã - çµæã¨ãã¦ãéã³ã³ãã¤ã©ã¯
[rbp+0xC]
ã[rbp+0x8]
ã[rbp+0x4]
ã®3åã®å¤ã常ã«0
ã®ã¾ã¾ã¨èª¤èªãã¦ã誤èªçµæã«åºã¥ãã¦åºåå 容ãæé©åãã¦ãã¾ãã¾ããF5
ãã¼ã§éã³ã³ãã¤ã«ç»é¢ãå表示ãããã³ã«ãOutput
ã¦ã£ã³ãã¦ä¸ã«12FC: conditional instruction was optimized away because %dwFilledByProc3.1==0
表示ãããã¦ãããã¨ãããåããã¾ãã
ä¾ãã°0x124F
ã®é¢æ°ãéã³ã³ãã¤ã«ãã¦ã¿ãã¨ã次ã®ããã«æ©è²ã®è¡¨ç¤ºãããã¾ããããã¯éã³ã³ãã¤ã©ã«ã¨ã£ã¦ä¸ç©ãªãã¨ã表ãã¦ãã¾ã:
ãªããæåã®ãã¡ã¯IDAã®__usercallå¼ã³åºãè¦ç´æå®ã使ã£ã¦ç¹æ®ãªå¼æ°ã®åå¨ãéã³ã³ãã¤ã©ã¸æãããã¨ãã¾ããããçµå±ã¯ãã¾ãããã¾ããã§ããã_DWORD *a2@<^0.8>
çã®æ§æã使ã£ã¦ããããããã¯ç¾å¨ã®é¢æ°ã®ã¹ã¿ãã¯ãã¬ã¼ã (ç¨èªããã£ã¦ãããä¸å®ã§ã)ã®ã¿ãåç
§ã§ããããã§ãã親é¢æ°ã®ã¹ã¿ãã¯ãã¬ã¼ã ãåç
§ãããã¨_DWORD *a2@<^-1.8>
çãå
¥åãã¦ã¿ã¾ããããæ§æã¨ã©ã¼ã¨ãªã£ã¦ãã¾ãã¾ããã
ã¾ããéã³ã³ãã¤ã«æ©è½ã®ãªãã·ã§ã³(IDAã¡ãã¥ã¼ã®Edit
âPlugins
âHex-Ray decompiler cloud Options
)ããã£ããè¦æ¸¡ãã¦ããä¸è¨æé©åãæå¶ã§ããããªé
ç®ã¯ç¡ãããã§ããã
éã¢ã»ã³ãã«ç»é¢ããå¦çå 容ãèªè§£
幸ãã0x1272
ã®é¢æ°ã¯çãã§ããéã¢ã»ã³ãã«å
容ããæ£ããå¦çãèªè§£ãããã¨ã«ãã¾ããã
GDBã§å®é¨ãããã¨ã§ãã©ããã0x124F
é¢æ°ã0x1272
é¢æ°ä¸ã®[rbp+0xC]
ãã0x122C
é¢æ°ã0x1272
é¢æ°ä¸ã®[rbp+0x8]
ãã0x1209
é¢æ°ã0x1272
é¢æ°ä¸ã®[rbp+0x4]
ããããããæ¸ãæããããããã¨ãåããã¾ããã
ã¾ãã0x12FC
ã®jz
å½ä»¤ãnop
ã§ä¸æ¸ãããã¨ãéã³ã³ãã¤ã«ç»é¢ããåå²ããªãã£ãå ´åã®å¤§ä½ã®å¦çãåããã¾ãã
èªè§£ããçµæã0x1272
ã®é¢æ°ã¯æ¬¡ã®å¦çãè¡ã£ã¦ãããã¨ãåããã¾ãã:
0x1272
é¢æ°ã®ç¬¬1å¼æ°ã¯ãå ¥åãã©ã°ã4æåãã¨ã«ã¾ã¨ããuint32_t
ã§ãã0x1272
é¢æ°ã®ç¬¬2å¼æ°ã¯ãuint32_t[4]
é åã§ããååå¼ã³åºãæã¯ãmain
é¢æ°ã§è¨å®ãã¦ããAlpacaHackRound8
æååã§ãã0x1272
é¢æ°ã®ã¹ã¿ãã¯ãã¬ã¼ã ã®[rbp + 0xC]
ã«ã__ROL4__(第2å¼æ°[0], 5) + __ROR4__(第2å¼æ°[1], 3)
ãæ¸ãè¾¼ã¿ã¾ãã0x1272
é¢æ°ã®ã¹ã¿ãã¯ãã¬ã¼ã ã®[rbp + 0x8]
ã«ã__ROR4__(第2å¼æ°[2], 3) - __ROL4__(第2å¼æ°[3], 5)
ãæ¸ãè¾¼ã¿ã¾ãã0x1272
é¢æ°ã®ã¹ã¿ãã¯ãã¬ã¼ã ã®[rbp + 0x4]
ã«ã[rbp + 0xC] ^ [rbp + 0x8] ^ 第1å¼æ°
ãæ¸ãè¾¼ã¿ã¾ãã[rbp + 0x4]
ã®æä¸ä½ãããã«ä¾åãã¦ã第2å¼æ°ã®4è¦ç´ ãããããXORã§æ´æ°ãã¾ãããã®éã¯[rbp + 0xC]
ã[rbp + 0x8]
ã使ãã¾ãã0x1272
é¢æ°èªä½ã®æ»ãå¤ã¯[rbp + 0x4]
ã§ãã
èªè§£ããçµæãã½ã«ãã¼ã§å©ç¨ãã¾ããã
ã½ã«ãã¼ã¨å®è¡çµæ
z3-solver
ã©ã¤ãã©ãªã§ã·ã³ããªãã¯å¤æ°ãç¨æãã¦ãèªè§£ãã0x1272
é¢æ°ãé©ç¨ããçµæãæ³å®ããçµæã«ãªãããã«ãå
¥åãéç®ããã½ã«ãã¼ãæ¸ãã¾ãã:
#!/usr/bin/env python3 import pwn import z3 MOD = 0x1_0000_0000 def byte_array_to_dword_array(a: bytes) -> list[int]: assert len(a) % 4 == 0 result: list[int] = [] for i in range(len(a) // 4): v: int = pwn.u32(a[i * 4 : (i + 1) * 4]) result.append(v) return result def RotateLeft32(value: int, bit: int) -> int: assert 0 <= bit < 32 assert 0 <= value < MOD return ((value << bit) | (value >> (32 - bit))) % MOD def RotateRight32(value: int, bit: int) -> int: assert 0 <= bit < 32 assert 0 <= value < MOD return ((value >> bit) | (value << (32 - bit))) % MOD def convert( part: int | z3.BitVecRef, work: list[int] ) -> tuple[int, int, int | z3.BitVecRef]: value1 = (RotateLeft32(work[0], 5) + RotateRight32(work[1], 3)) % MOD value2 = (RotateRight32(work[2], 3) - RotateLeft32(work[3], 5) + MOD) % MOD value3 = (part ^ value1 ^ value2) % MOD # ããã§value3ã§åå²ãã¦ãã¾ãã¨ãã·ã³ããªãã¯å¤æ°ã®ã¾ã¾ã ãããæã£ãåå²ã«ãªãã¾ããã§ãããå¾ã§å¤æãã¾ã # æè¨: ã(value3 & 1) != 0ãçã§ãSymbolic expressions cannot be cast to concrete Boolean values.ããåºãã¨ãã¯æ¬å½ã«ééã£ã¦ãã¾ãã return (value1, value2, value3) # fmt:off # 4040ããShift+Eã§Export data expected_bytes = bytes.fromhex("DC 86 1A 9A DD 93 9B 35 D3 74 DA EE E8 5A 3C C5 1C 64 33 47 D2 3B 28 F3 CC 5A 48 8B 74 0C 4B 87 38 D6 80 40 51 E6 4A 27 A1 73 52 0F 93 06 54 3D 65 13 FB C8 65 AF D2 67 B3 09 EF 7D 23 A6 76 E5 13 10 13 FF 34 8D AE D0 9C 2C 4D F3 A1 BC 46 2F 98 87 B6 57 1A A2 17 F1 F0 E5 B0 BA 9B 6D B5 A7 AC 6A 5E AC E8 F6 90 D8 B0 A2 99 91") expected_dwords = byte_array_to_dword_array(expected_bytes) assert len(expected_dwords) == 27 # fmt:on work: list[int] = byte_array_to_dword_array(b"AlpacaHackRound8") solver = z3.Solver() flag_input = [z3.BitVec(f"flag_{i:02d}", 8) for i in range(4 * 27)] for i in range(len(flag_input) // 4): value_input = ( (z3.ZeroExt(32, flag_input[(4 * i) + 0]) << 0) | (z3.ZeroExt(32, flag_input[(4 * i) + 1]) << 8) | (z3.ZeroExt(32, flag_input[(4 * i) + 2]) << 16) | (z3.ZeroExt(32, flag_input[(4 * i) + 3]) << 24) ) (value1_concret, value2_concret, value3_symbolic) = convert(value_input, work) solver.add(value3_symbolic == expected_dwords[i]) if solver.check() != z3.sat: raise Exception("Can not solve...") # ãªãã¯ãã®å¤ã¯åãã£ã¦ããã®ã§ãç°¡åã®ãããã¡ãã使ãã¾ã value3_concrete = expected_dwords[i] if (value3_concrete & 1) == 1: work[0] ^= RotateLeft32(value2_concret, 11) work[1] ^= RotateLeft32(value2_concret, 13) work[2] ^= RotateRight32(value1_concret, 15) work[3] ^= RotateRight32(value1_concret, 13) else: work[0] ^= RotateRight32(value2_concret, 13) work[1] ^= RotateRight32(value2_concret, 15) work[2] ^= RotateLeft32(value1_concret, 13) work[3] ^= RotateLeft32(value1_concret, 11) flag_result = "" model = solver.model() for f in flag_input: flag_result += chr(model[f].as_long()) # type:ignore print(flag_result.strip("\x00"))
å®è¡ãã¾ãã:
$ ./solve.py Alpaca{th15_f145_1s_3xc3ssiv3ly_l3ngthy_but_th1s_1s_t0_3nsur3_th4t_1t_c4nn0t_b3_e4s1ly_s01v3d_us1ng_angr} $ ./hidden 'Alpaca{th15_f145_1s_3xc3ssiv3ly_l3ngthy_but_th1s_1s_t0_3nsur3_th4t_1t_c4nn0t_b3_e4s1ly_s01v3d_us1ng_angr}' congratz $
ãã©ã°ãå
¥æã§ãã¾ãã: Alpaca{th15_f145_1s_3xc3ssiv3ly_l3ngthy_but_th1s_1s_t0_3nsur3_th4t_1t_c4nn0t_b3_e4s1ly_s01v3d_us1ng_angr}
ãªããã³ã³ãã¹ãä¸ã§ã¯ã½ã«ãã¼ãã²ããããã°ããã¦ãã¦ã1æéãããããã£ã¦ãã¾ãã:
2**32
ãä¿æãããã£ãMOD
å¤æ°ã®å 容ãã0ã1ã¤å¤ã0x1_0000_00000
ã¨ãã¦ãã¾ã£ã¦ãã¾ããâ¦â¦ã- éã³ã³ãã¤ã«ç»é¢ãéã¢ã»ã³ãã«ç»é¢ãæãèªã¿ãã¦ãã¦ã
ror
å½ä»¤ã®åå¨ãè¦éãã¦ãã¾ãããå ¨é¨rol
å½ä»¤ã¨æã£ã¦ãã¾ããâ¦â¦ã - 確ããz3ã®
BitVecRef
åå¤æ°value
ã使ã£ã¦if (value & 1) != 0
çã¨æ¡ä»¶åå²ããããã¨ãã¦ãã¾ããâ¦â¦:if (value & 1) != 0:
表è¨ã§ã¯Symbolic expressions cannot be cast to concrete Boolean values.
ä¾å¤ãéåºããã¾ããããã®æç¹ã§æªããã¨æ°ã¥ãã¦ããã°â¦â¦ãif (value & 1) == 1:
表è¨ã§ã¯å®è¡ã§ããã¾ããããvalue3
ã¯ã·ã³ããªãã¯å¤æ°ã®ã¾ã¾ãªã®ã§æ³å®ããæ¡ä»¶åå²ã«ãªããªãã£ãããã§ã(ã©ã®ããã«å®è¡ããã¦ãããã¯åãã£ã¦ãã¾ãã)ã
[Rev] subway (8 solves, 304 points)
This is true floating-point arithmetic.
æ¬åé¡ãã¤ããªãIDAã§è§£æãããã¡ã¤ã«subway.i64ãå ¬éãã¦ãã¾ãã
é
å¸ãã¡ã¤ã«ã¨ãã¦ãsubway
ãããã¾ãã:
$ file * subway: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8c54e5ca98b13d7863a00517ae1aeb7722aa6103, for GNU/Linux 3.2.0, stripped $
åé¡æãããã¦æµ®åå°æ°ç¹æ°ã使ããã¦ããæ°é ãæãã¤ã¤ãIDAã§éãã¦éã³ã³ãã¤ã«ãã¾ããã
+0
ã¨-0
ã®çºè¦
å種å¦çãçºãã¦ããã¨ãmalloc
ã§ç¢ºä¿ããè¦ç´ ã¸æ ¼ç´ããå¤ã¯ãuint32_t
åã®0
ã0x80000000
ã ãã§ãããã¨ãåããã¾ããããã¦æçµçã«0x21B1
ã®é¢æ°ã§ãfloat
åã¨ãã¦æ±ã£ã¦ãããã¨ãåããã¾ãã
ããã§ãè¦ã¤ãã£ãå¤ã®ããã表ç¾ããfloat
(=float32
)ã¨ãã¦è§£éããã¦ã¿ã¾ããIEEE-754 Floating Point Converterãµã¤ãã使ãã¾ãããããã¨ã0
ã¯+0
ã0x80000000
ã¯-0
ã¨åããã¾ãããæµ®åå°æ°ç¹æ°ã¯ç¬¦å·ããããåå¨ããããã0
ã«ãæ£è² ãåå¨ãã¾ãã
ããã¦ãä¸çªæå¾ã®æ£èª¤å¤å®ç¨ã«0x2092
ã®é¢æ°ã®æ»ãå¤ã使ç¨ãã¦ãã¾ãã次ã®å
容ã§ã:
bool __fastcall sub_2092(__m128i a1) { return _mm_cvtsi128_si32(a1) >= 0; }
ä¸è¦ããã¨ã__m128i
ã¨ããè¬ã®åãå¼æ°ã¨ãã¦ããããã«è¦ãã¾ããããããx86 psABIs / x86-64 psABI · GitLabãããã¦ã³ãã¼ãã§ããSystem V Application Binary Interfaceè³æã®Figure 3.4: Register Usage
ãè¦ãã¨ã%xmm0-%xmm1
ã¬ã¸ã¹ã¿ã®ç¨éãused to pass and return floating point arguments
ã¨ããã¾ããã¤ã¾ãã1åã®float
å¤ã渡ãå ´åã§ãã128-bitå¹
ã®xmm0
ã¬ã¸ã¹ã¿ã使ããã¾ããã¾ãã_mm_cvtsi128_si32å½ä»¤ã®è§£èª¬ãèªãã¨ãä¸ä½32-bitæ´æ°ãè¿ãå½ä»¤ã¨åããã¾ãã
ã©ããã0x2092
é¢æ°ã¯ããå¼æ°ã®float
å¤ã®ããã表ç¾ãint
åã¨ã¿ãªããæã0以ä¸ãã©ããããè¿ãããã§ãããã£ã¨ããã¨ã2ã®è£æ°è¡¨è¨ã使ããã¦ããã·ã¹ãã ã§int
åã0以ä¸ã«ããã®ã¯æä¸ä½ãããã0
ã§ããå ´åã¨å義ã§ãããã¯float
åã®å ´åã¯ç¬¦å·ãããã0
ã®å ´åã¨å義ã§ããçµå±ã®ã¨ãã0x2092
é¢æ°ã¯ãå¼æ°ã®float
å¤ãæ£ã®å¤ã®å ´åã¯true
ããè² ã®å¤ã§ããå ´åã¯false
ãè¿ãé¢æ°ã§ãã
ãã®ããã«ãã©ããã+0
ã¨-0
ã®ç¬¦å·ãããã ãã使ã£ã¦ä½ãããã¦ããããããã¨ãããã¨ãåãã£ã¦ãã¾ã
True
ãFalse
ãè«çé¢æ°ãç®è¡é¢æ°çã®çºè¦
+0
ã¨-0
ã®ç¬¦å·ãããã§æ
å ±ã表ãã¦ããããããã¨ãèãã¤ã¤ãã¤ããªä¸ã®å種é¢æ°ãæ¢ãã¦ã¿ãã¨ãã©ããã+0
ãTrue
ãã-0
ãFalse
ã表ãããããã¨ãåãã£ã¦ãã¾ãããã®ä¸ã§ãè«çé¢æ°ãè¦ã¤ããã¾ããè«çé¢æ°ã¯ãfloat
åã®å¤ãå¼æ°ã«åãã¾ã:
0x11A9
ã®é¢æ°: 符å·å転ãã¤ã¾ãè«çNOTã0x11B1
ã®é¢æ°: è«çORã0x11D5
ã®é¢æ°: è«çANDããã¢ã«ã¬ã³ã®æ³åã§å®è£ ããã¦ãã¾ãã0x120B
ã®é¢æ°: 2å¼æ°ã®XORã0x125A
ã®é¢æ°: 3å¼æ°ã®XORã0x1279
ã®é¢æ°: 3å¼æ°ã®ãã¡2å以ä¸ã+0
ãªãæ»ãå¤ã¯+0
ãããã§ãªããªãæ»ãå¤ã¯-0
ã
ã¾ããfloat[32]
(=float*
)åããå
é indexãLSBã表ãuint32_t
åã表ããã¨ãåãã£ã¦ãã¾ããæ§ç¯ç¨ã®é¢æ°ã§ã:
0x12DD
ã®é¢æ°:0
ç¨ãã¤ã¾ãå ¨è¦ç´ ã-0
ã®float[32]
ãè¿ãã¾ãã0x130F
ã®é¢æ°:uint8_t
åãå¼æ°ã«ããã®å¤ã表ãfloat[32]
ãè¿ãã¾ããé åã®å é è¦ç´ ãLSBã表ãã¾ãã以éåæ§ã§ãã0x13F2
ã®é¢æ°:uint32_t
åãå¼æ°ã«ããã®å¤ã表ãfloat[32]
ãè¿ãã¾ãã
float[32]
ã丸ãã¨æ±ãè«çé¢æ°ãããã¾ã:
0x139D
ã®é¢æ°: 2ã¤ã®float[32]
ã®è¦ç´ ãã¨ã®è«çORãåã£ãæ°ããfloat[32]
ãè¿ãã¾ãã0x1548
ã®é¢æ°: 2ã¤ã®float[32]
ã®è¦ç´ ãã¨ã®è«çXORãåã£ãæ°ããfloat[32]
ãè¿ãã¾ãã
ç®è¡é¢æ°ã¯float[32]
åã®å¤2ã¤ãå¼æ°ã«åãã¾ããã¤ã¾ããå®è³ªçã«uint32_t
å士ã®æ¼ç®ã¨å義ã§ã:
0x14C2
ã®é¢æ°: åãè¨ç®ãã¦è¿ãã¾ãã0x1430
ã®é¢æ°: å·®ãè¨ç®ãã¦è¿ãã¾ãã0x209C
ã®é¢æ°: ç©ãè¨ç®ãã¦è¿ãã¾ãã
ãã®ä»ãfloat[32]
ã®è¦ç´ ã移åãããé¢æ°ã1ã¤ããã¾ã:
0x134D
ã®é¢æ°: 第1å¼æ°ã®float[32]
ãã第2å¼æ°ã®æ°å¤åæ°ã ãå é ããé¤å¤ãã¦ãå¾ãã¸-0
è¦ç´ ãè©°ãããã¨ã¨å義ã®ãæ°ããfloat[32]
ãè¿ãã¾ãã
ãªããå¼æ°ã__m128
åã§ããé¢æ°ã¯ãå¼æ°ãfloat
åã¸å¤æããã¨èªã¿ããããªãã¾ãããä¾ãã°0x11A9
ã®é¢æ°ã¯ãIDAã¯åæç¶æ
ã§ã¯æ¬¡ã®è¡¨ç¤ºã§ã:
__m128 __fastcall sub_11A9(__m128 a1) { return _mm_xor_ps(a1, (__m128)xmmword_3640); }
ããã§å¼æ°ãæ»ãå¤ã®åãfloat
ã¸å¤æ´ããã¨ã符å·å転ãè¡ããã¨ãæ確ãªè¡¨ç¤ºã«ãªãã¾ãã:
float __fastcall sub_11A9(float a1) { return -a1; }
ã¾ããPythonã§åä½æ¤è¨¼ãããéã¯ãmath.copysigné¢æ°ã使ãã®ãç°¡åã§ãããåä½æ¤è¨¼ã«ä½¿ã£ãã³ã¼ãã¯GitHubã§ã®test.pyã§å ¬éãã¦ãã¾ãã
(ã¨ããã§ã+0 + -0
ã¯+0
ã«ãªãã®ã¯ä¿è¨¼ããã¦ãããããæ°ã«ãªã£ãã®ã§èª¿ã¹ã¦ã¿ã㨠c++ - What is (+0)+(-0) by IEEE floating point standard? - Stack Overflow ãè¦ã¤ããã¾ãããæ°å¤ä¸¸ãè¨å®ã«ä¾åããããã§ãï¼ãã å®é¨ãã㨠+0
ã«ãªã£ãã®ã§ã+0
ã«ãªãã¨ä»®å®ãã¦ç¶ãã¾ããã)
å ¨ä½ã®æµãã®è§£èª
main
é¢æ°ã¯æ¬¡ã®ãã¨ãè¡ãã¾ã:
0x2221
ä»è¿ã§ãã³ãã³ãã©ã¤ã³å¼æ°ãä¸ãããã¦ãããã¨ãæ¤è¨¼ãã¾ãã0x222F
ä»è¿ã§ãã³ãã³ãã©ã¤ã³å¼æ°ã®é·ãã44æåã§ãããã¨ãæ¤è¨¼ãã¾ãã0x226B
ã§å¼ã³åºã0x159D
ã®é¢æ°ã§ãã³ãã³ãã©ã¤ã³å¼æ°4æåã®8bitå==32bitãã¨ã«ãbitãONãªã+0
ãOFFãªã-0
ãæã¤float[32]
ãã44/4
ã®11
è¦ç´ åä½æãã¾ããå ¨ä½ã¨ãã¦uint32_t[11]
ç¸å½ã«ãªãã¾ãã0x2273
ã§å¼ã³åºã0x20FE
ã®é¢æ°ã§ãuint32_t[11]
ç¸å½ã®å種è¦ç´e
ã«ã¤ãã¦ã((e * 34974707) ^ 2238381247)
ã¸å¤æãã¾ãã0x227B
ã§å¼ã³åºã0x167A
ã®é¢æ°ã§ãuint32_t[11]
ç¸å½ã®å種è¦ç´ ã«ã¤ãã¦åãå·®ã使ã£ãè¤éãªå¤æãè¡ãã¾ãã- èªãã§ãã¾ããã
z3-solver
ã§éç®ãã¾ãã
- èªãã§ãã¾ããã
0x2283
ã§å¼ã³åºã0x21B1
ã®é¢æ°ã§ãå¤æçµæãæ³å®ã®çµæã«ãªã£ã¦ãããå¤å®ãã¾ãã0x3040
以éã«ããfloat[11][32]
ç¸å½ã®ãã¼ã¿ã使ã£ã¦ãã¾ããã使ã£ã¦ããã®ã¯ç¬¦å·ãããã®ã¿ã§ããæ®ãã®ä»®æ°é¨ãææ°é¨ãé¢å¿å¤ã§ãã
- å¤å®çµæãåºåãã¾ãã
ã½ã«ãã¼ã¨å®è¡çµæ
0x167A
ã®é¢æ°ã®éã³ã³ãã¤ã«çµæãæ´å½¢ãã¦ãã½ã«ãã¼ã®z3-solver
ã§éç®ãã¾ããããã®æ´å½¢çµæã400è¡ã«ãåã¶ãããæ¬è¨äºä¸ã«ã¯æ²è¼ãã¾ããã詳細ã¯GitHubããåç
§ãã ããã
0x167A
ã®é¢æ°ã®éã³ã³ãã¤ã«çµæã®ãã¡ãä»£å ¥çãä¼´ãéè¦ãªé¨åãæç²ãã¦decompiled_167A.txtã¸ä¿åãã¾ãããdecompiled_167A.txt
ã®å 容ãPythonã§å®è¡ã§ãããããå å·¥ããå¦çãparse.pyã¸å®è£ ãã¾ãããparse.py
ã®å®è¡çµæãsolve.pyã®convert_list_complexly
é¢æ°ã®æ¬ä½ç®æã¸è²¼ãä»ãã¾ããã
æçµçãªã½ã«ãã¼ãå®è¡ãã¾ãã:
$ time ./solve.py Alpaca{l0gic4l_0per4ti0ns_by_subtr4ction_;D} ./solve.py 1.70s user 0.08s system -245% cpu -0.728 total $ ./subway 'Alpaca{l0gic4l_0per4ti0ns_by_subtr4ction_;D}' congratz $
æ°ç§ã§ãã©ã°ãå
¥æã§ãã¾ãã: Alpaca{l0gic4l_0per4ti0ns_by_subtr4ction_;D}
ãªãã³ã³ãã¹ãä¸ã§ã¯ãä½æ
ãæ¬æ¥ã¨ã¯éã®ã+0
ãFalse
ã-0
ãTrue
ã®è«çä½ç³»ãããï¼ãã¨èª¤è§£ãã¦ãã¾ã£ã¦ãã¾ããããªã«ãè¾»è¤ãåããªãã¨å½·å¾¨ãã¾ãã£ãå¾ã«ãããããæ°ä»ãã¾ããã
ææ³
- AlpacaHackåå 7åç®ã§ã®ãåã®1æ¡é ä½ã§ãï¼
- ã¹ããããã3åç®ã¯ãC++製ã®è¤éãããªåé¡ã§ããã4åç®ã®
subway
åé¡ã®ã»ããèªè§£ãç´ ç´ããã ã£ãã®ã§ããã¡ãã«èµ°ãã¾ãããçµäº6ååã«ã®ãªã®ãªã§æ£è§£ã§ãã¾ããï¼ - èªè§£ãéç®ã大å¤ãªå¦çã
z3-solver
ã«ä»»ããããã¨ããã£ã±ã楽ã§ãã hidden
åé¡ã®èéã³ã³ãã¤ã«ãé¢ç½ãã£ãã§ãï¼subway
åé¡ã§ããè¬ã®ç¶æ ãæã¡ã¤ã¤ã«ã¼ããã¦ããé¢æ°ããããâãããããããå ¨å ç®å¨ã®carry bitã§ã¯ï¼ãâã足ãç®é¢æ°ã ã£ãï¼ãçã®çºè¦ãã¦ããã®ãé¢ç½ãã£ãã§ãï¼