20170408_ASISCTF Writeup

A fine OTP Server

First, I connect the given site. In this site, I can command F/S/G/P/E/Q as below.
Case of F/S, encrypted stirng is displayed.   And Encrypt Function is displayed in “E” command. Also public key is shown in “P” command.
In “G” command, I need to input correct OTP string.
$ nc 66.172.27.77 35156
|————————————-|
| Welcome to the S3cure OTP Generator |
|————————————-|
| Guess the OTP and get the nice flag!|
| Options:
    [F]irst encrypted OTP
    [S]econd encrypted OTP
    [G]uess the OTP
    [P]ublic key
    [E]ncryption function
    [Q]uit
F
13424849164527521403756445050870196571038349263738328860728317613249912394547060932323343839684520029298203039106900245311207700034998334716959146479549063889540706152154598347254408345543188674922713000891547296629021076472870040539376739314713832772692506639957575066582478623205952405554199517614557654950955573511290458637377044071644643695182159213250790297373664287783665077558548590013992923904092081201939570770508246233526911821723989693584742610070212351991512679896373811561604036362799977744239761678600524058050872970272966843600157676880214915454293
S
13424849164527521403756445050870196571038349263738328860728317613249912394547060932323343839684520029298203039106900245311207700034998334716959144596327888987483332490055908508853395279660155002644916321473620423782059398196874803570889888021013555969780441819173091267534124741585823823928977022296472573786767119234652517576883082612632421073030618602126508756749230654589167402408793504098055206952441309746437159943776038201471785917248460328942218634398236191051477075764560901206858572045306618762342065512902611924464286185405382441808373146820149030892864
P
the public key is:
—–BEGIN PUBLIC KEY—–
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA78LIZcHia4rGA4veXGvi
BaSzN+Vtx1yChcXVBL3EGgY93KRn4JxAC01V5Nzbo7E0U4OreV35m4jJH2o/xYp3
kXqjFqssJ/PCHTWFXEA+wcP7rVO6zl4xsSknjCM/Zp3k97SjaORtFA5U/skHCasQ
6QmsBYvLr/5JIJgScxeUymPT9NKpVmEBmRJvJHf9rEEx6tz/g2LFEK7EFmIi4dwv
YslK70uyl6HHz6AwZqxDrOxy4Y5cJNTj0o1AA8pVXNGmf3KqF4hb5H0hkvareQUy
4GSqnmqdwuEIiOtvz1ts9jqxqeF0OVvBq1iqO+05PU+IqJymnwUbe6lBoAaryV21
/QIBAw==
—–END PUBLIC KEY—–
At first, Encrypt Function is as below. I recognize that e is very small value (e=3) enough to decrypt cipher text to root it.
def gen_otps():
    template_phrase = ‘Welcome, dear customer, the secret passphrase for today is: ‘
    OTP_1 = template_phrase + gen_passphrase(18)
    OTP_2 = template_phrase + gen_passphrase(18)
    otp_1 = bytes_to_long(OTP_1)
    otp_2 = bytes_to_long(OTP_2)
    nbit, e = 2048, 3
    privkey = RSA.generate(nbit, e = e)
    pubkey  = privkey.publickey().exportKey()
    n = getattr(privkey.key, ‘n’)
    r = otp_2 – otp_1
    if r < 0:
        r = -r
    IMP = n – r**(e**2)
    if IMP > 0:
        c_1 = pow(otp_1, e, n)
        c_2 = pow(otp_2, e, n)
    return pubkey, OTP_1[-18:], OTP_2[-18:], c_1, c_2
So I try to make script to do cube root cipher text.
import sys
import gmpy
def root_e(c, e, n):
bound = gmpy.root(n, e)[0]
m = gmpy.root(c, e)[0]
return m, bound
if __name__ == ‘__main__’:
n = 0x00efc2c865c1e26b8ac6038bde5c6be205a4b337e56dc75c8285c5d504bdc41a063ddca467e09c400b4d55e4dcdba3b1345383ab795df99b88c91f6a3fc58a77917aa316ab2c27f3c21d35855c403ec1c3fbad53bace5e31b129278c233f669de4f7b4a368e46d140e54fec90709ab10e909ac058bcbaffe49209812731794ca63d3f4d2a956610199126f2477fdac4131eadcff8362c510aec4166222e1dc2f62c94aef4bb297a1c7cfa03066ac43acec72e18e5c24d4e3d28d4003ca555cd1a67f72aa17885be47d2192f6ab790532e064aa9e6a9dc2e10888eb6fcf5b6cf63ab1a9e174395bc1ab58aa3bed393d4f88a89ca69f051b7ba941a006abc95db5fd
e = 3
enc1 = 13424849164527521403756445050870196571038349263738328860728317613249912394547060932323343839684520029298203039106900245311207700034998334716959146479549063889540706152154598347254408345543188674922713000891547296629021076472870040539376739314713832772692506639957575066582478623205952405554199517614557654950955573511290458637377044071644643695182159213250790297373664287783665077558548590013992923904092081201939570770508246233526911821723989693584742610070212351991512679896373811561604036362799977744239761678600524058050872970272966843600157676880214915454293
enc2 = 13424849164527521403756445050870196571038349263738328860728317613249912394547060932323343839684520029298203039106900245311207700034998334716959144596327888987483332490055908508853395279660155002644916321473620423782059398196874803570889888021013555969780441819173091267534124741585823823928977022296472573786767119234652517576883082612632421073030618602126508756749230654589167402408793504098055206952441309746437159943776038201471785917248460328942218634398236191051477075764560901206858572045306618762342065512902611924464286185405382441808373146820149030892864
m, bound = root_e(enc1, e, n)
print “%d (possible solution under %d)” % (m, bound)
print hex(m)
m, bound = root_e(enc2, e, n)
print “%s (possible solution under %s)” % (hex(m), hex(bound))
print hex(m)
I get public key as below way.
$ openssl rsa -in pub.pem -text -pubin
Public-Key: (2048 bit)
Modulus:
    00:ef:c2:c8:65:c1:e2:6b:8a:c6:03:8b:de:5c:6b:
    e2:05:a4:b3:37:e5:6d:c7:5c:82:85:c5:d5:04:bd:
    c4:1a:06:3d:dc:a4:67:e0:9c:40:0b:4d:55:e4:dc:
    db:a3:b1:34:53:83:ab:79:5d:f9:9b:88:c9:1f:6a:
    3f:c5:8a:77:91:7a:a3:16:ab:2c:27:f3:c2:1d:35:
    85:5c:40:3e:c1:c3:fb:ad:53:ba:ce:5e:31:b1:29:
    27:8c:23:3f:66:9d:e4:f7:b4:a3:68:e4:6d:14:0e:
    54:fe:c9:07:09:ab:10:e9:09:ac:05:8b:cb:af:fe:
    49:20:98:12:73:17:94:ca:63:d3:f4:d2:a9:56:61:
    01:99:12:6f:24:77:fd:ac:41:31:ea:dc:ff:83:62:
    c5:10:ae:c4:16:62:22:e1:dc:2f:62:c9:4a:ef:4b:
    b2:97:a1:c7:cf:a0:30:66:ac:43:ac:ec:72:e1:8e:
    5c:24:d4:e3:d2:8d:40:03:ca:55:5c:d1:a6:7f:72:
    aa:17:88:5b:e4:7d:21:92:f6:ab:79:05:32:e0:64:
    aa:9e:6a:9d:c2:e1:08:88:eb:6f:cf:5b:6c:f6:3a:
    b1:a9:e1:74:39:5b:c1:ab:58:aa:3b:ed:39:3d:4f:
    88:a8:9c:a6:9f:05:1b:7b:a9:41:a0:06:ab:c9:5d:
    b5:fd
Exponent: 3 (0x3)
writing RSA key
—–BEGIN PUBLIC KEY—–
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA78LIZcHia4rGA4veXGvi
BaSzN+Vtx1yChcXVBL3EGgY93KRn4JxAC01V5Nzbo7E0U4OreV35m4jJH2o/xYp3
kXqjFqssJ/PCHTWFXEA+wcP7rVO6zl4xsSknjCM/Zp3k97SjaORtFA5U/skHCasQ
6QmsBYvLr/5JIJgScxeUymPT9NKpVmEBmRJvJHf9rEEx6tz/g2LFEK7EFmIi4dwv
YslK70uyl6HHz6AwZqxDrOxy4Y5cJNTj0o1AA8pVXNGmf3KqF4hb5H0hkvareQUy
4GSqnmqdwuEIiOtvz1ts9jqxqeF0OVvBq1iqO+05PU+IqJymnwUbe6lBoAaryV21
/QIBAw==
—–END PUBLIC KEY—–
$ python solve_otp.py
237667503860111710965249653350625517263440306798910137876859435749199905356736154796944115797449476461699808094618740739874497850440521756435958303032367961
40535050836466712688135359265357 (possible solution under 31164236177314283628208254336126607000897573704651962729479153080499433841714954634001811713695031
247441658525447514248227685519410093562869317175884995069327255163393409948737015989839999322052569596253947)
0x57656c636f6d652c206465617220637573746f6d65722c2074686520736563726574207061737370687261736520666f7220746f6461792069733a2051333944666f644231704743586c48417a
4d
0x57656c636f6d652c206465617220637573746f6d65722c2074686520736563726574207061737370687261736520666f7220746f6461792069733a2044715674766c716f5345556c7675396763
34 (possible solution under 0x6365fde8b4e5593eb05fd19f76893f527a9a5a8fc8b7bf8b2edf613423c94fdd6bc03d7a5807599fb024011ba5e2cd808ae4cbc622d19a47be94bb4bea3cdd
08a8b7f38c523f1a30de1f908e81d6e1060bcbc6556fb)
0x57656c636f6d652c206465617220637573746f6d65722c2074686520736563726574207061737370687261736520666f7220746f6461792069733a2044715674766c716f5345556c7675396763
34
Ascii-decode output and get the flag.
G
Send me the otp 🙂
Q39DfodB1pGCXlHAzM
Woow, you got the flag 🙂 ASIS{0f4ae19fefbb44b37f9012b561698d19}

Wandere bits

At first, I analyze given file by IDA-Pro. Then I realize that this file compare encoded user input and  “828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a583”
But I don’t know how to encode user input.
Then I try to know how to encode, and I compare user input and output.
When I input “ABCDEFGHIJKLMNOPQRSTUVWXYZA ” -> “828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a58
After some try, I realize that a character decide 2-character code such as “A” is “82”, but last character is particular value “+1”.
gdb-peda$ start ABCDEFGHIJKLMNOPQRSTUVWXYZA
warning: the debug information found in “/lib64/ld-2.23.so” does not match “/lib64/ld-linux-x86-64.so.2” (CRC mismatch).
[———————————-registers———————————–]
RAX: 0x400fb0 (<main>:    push   rbx)
RBX: 0x0
RCX: 0xe0
RDX: 0x7fffffffd8e0 –> 0x7fffffffdda5 (“LC_PAPER=en_US.UTF-8”)
RSI: 0x7fffffffd8c8 –> 0x7fffffffdd2f (“/mnt/hgfs/VM-Share/20170408_ASISCTF/Wandere_bits_7f6b94729b459d692265f3e51128ced40065ed52”)
RDI: 0x2
RBP: 0x406940 (<__libc_csu_init>:    push   r15)
RSP: 0x7fffffffd7e8 –> 0x7ffff7496830 (<__libc_start_main+240>:    mov    edi,eax)
RIP: 0x400fb0 (<main>:    push   rbx)
R8 : 0x7ffff7dd4ac0 –> 0x7ffff7dcf838 –> 0x7ffff7b76f60 (<_ZNSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEED2Ev>:    )
R9 : 0x7ffff7dc9780 –> 0x7ffff7dc8918 –> 0x7ffff7ae0d40 (<_ZN10__cxxabiv117__class_type_infoD2Ev>:    mov    rax,QWORD PTR [rip+0x2efc81]        # 0x7ffff7dd09c8)
R10: 0x32f
R11: 0x7ffff74b0280 (<__GI___cxa_atexit>:    push   r12)
R12: 0x4011d0 (<_start>:    xor    ebp,ebp)
R13: 0x7fffffffd8c0 –> 0x2
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[————————————-code————————————-]
   0x400faa:    add    BYTE PTR [rax],al
   0x400fac:    add    BYTE PTR [rax],al
   0x400fae:    add    BYTE PTR [rax],al
=> 0x400fb0 <main>:    push   rbx
   0x400fb1 <main+1>:    add    rsp,0xffffffffffffff80
   0x400fb5 <main+5>:    mov    rax,QWORD PTR fs:0x28
   0x400fbe <main+14>:    mov    QWORD PTR [rsp+0x78],rax
   0x400fc3 <main+19>:    xor    eax,eax
[————————————stack————————————-]
0000| 0x7fffffffd7e8 –> 0x7ffff7496830 (<__libc_start_main+240>:    mov    edi,eax)
0008| 0x7fffffffd7f0 –> 0x0
0016| 0x7fffffffd7f8 –> 0x7fffffffd8c8 –> 0x7fffffffdd2f (“/mnt/hgfs/VM-Share/20170408_ASISCTF/Wandere_bits_7f6b94729b459d692265f3e51128ced40065ed52”)
0024| 0x7fffffffd800 –> 0x2ffffd8e0
0032| 0x7fffffffd808 –> 0x400fb0 (<main>:    push   rbx)
0040| 0x7fffffffd810 –> 0x0
0048| 0x7fffffffd818 –> 0x4a94056c35949fdb
0056| 0x7fffffffd820 –> 0x4011d0 (<_start>:    xor    ebp,ebp)
[——————————————————————————]
Legend: code, data, rodata, value
Temporary breakpoint 13, 0x0000000000400fb0 in main ()
gdb-peda$ C
Continuing.
[———————————-registers———————————–]
RAX: 0x7fffffffd760 –> 0x61c5a0 (“828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a583“)
RBX: 0x0
RCX: 0x0
RDX: 0x0
RSI: 0x0
RDI: 0x7ffff7839b20 –> 0x100000000
RBP: 0x406940 (<__libc_csu_init>:    push   r15)
RSP: 0x7fffffffd760 –> 0x61c5a0 (“828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a583”)
RIP: 0x401098 (<main+232>:    mov    esi,0x4069f8)
R8 : 0x61c4b0 –> 0x61c4f0 –> 0xb0
R9 : 0x1
R10: 0x7ffff7839b78 –> 0x61d2c0 –> 0x0
R11: 0x7ffff7839b78 –> 0x61d2c0 –> 0x0
R12: 0x4011d0 (<_start>:    xor    ebp,ebp)
R13: 0x7fffffffd8c0 –> 0x2
R14: 0x0
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[————————————-code————————————-]
   0x40108c <main+220>:    mov    rdi,rsp
   0x40108f <main+223>:    mov    DWORD PTR [rsp+0x70],eax
   0x401093 <main+227>:    call   0x401390 <_Z6wapintB5cxx119BigNumber>
=> 0x401098 <main+232>:    mov    esi,0x4069f8
   0x40109d <main+237>:    mov    rdi,rsp
   0x4010a0 <main+240>:    call   0x400f10 <_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEPKc@plt>
   0x4010a5 <main+245>:    mov    rdi,QWORD PTR [rsp]
   0x4010a9 <main+249>:    mov    ebx,eax
[————————————stack————————————-]
0000| 0x7fffffffd760 –> 0x61c5a0 (“828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a583”)
0008| 0x7fffffffd768 –> 0x36 (‘6’)
0016| 0x7fffffffd770 –> 0x36 (‘6’)
0024| 0x7fffffffd778 –> 0x400eb0 (<_ZNSt8ios_base4InitD1Ev@plt>:    jmp    QWORD PTR [rip+0x2071aa]        # 0x608060)
0032| 0x7fffffffd780 –> 0x61cac0 (‘0’ <repeats 200 times>…)
0040| 0x7fffffffd788 –> 0x800
0048| 0x7fffffffd790 –> 0x800
0056| 0x7fffffffd798 –> 0x3
[——————————————————————————]
Legend: code, data, rodata, value
Breakpoint 1, 0x0000000000401098 in main ()
So I solve this by coding below scrypt
<code>
”’
abcdefghijklmnopqrstuvwxyz
929193989a999b949695979c9e9d9fb0b2b1b3b8bab9bbb4b6b5
ABCDEFGHIJKLMNOPQRSTUVWXYZ
828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a5
0123456789{}+_-a
30323133383a393b3436b7be17af1e
”’
str = “abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}+_-“
code = “929193989a999b949695979c9e9d9fb0b2b1b3b8bab9bbb4b6b5828183888a898b848685878c8e8d8fa0a2a1a3a8aaa9aba4a6a530323133383a393b3436b7be17af1e”
def make_code_list(str):
list = []
count = 0
tmp =””
for i in str:
     tmp += i
     if(count%2 ==1):
          list.append(tmp)
          tmp = “”
     count +=1
return list
str_list = list(str)
print str_list
code_list = make_code_list(code)
enc_list = make_code_list(“82a386a3b7983198313b363293399232349892369a98323692989a313493913036929a303abe”)
print enc_list
flag = “”
for i in enc_list:
     flag += str[code_list.index(i)]
print flag
</code>

Piper TV

Open given file by wireshark. and I can see many long packet (more than 1500 byte).
I realize that this may be movie file because its title is piper “TV”.
So I extract file by wireshark Analyze->Follow->TCP Stream.
Then select Show and Save data to Raw, and Save it.
Input saved data to file command, and recognize that this data is MPEG Data.
So change this file’s extention to .ts and open it by VLC
$ file PiperTV.bin
PiperTV.bin: MPEG transport stream data
Finally I find flag in the movie.

Leave a comment