ybin – paste data privately

Arguing that you don't care about the right to privacy because you have nothing to hide is no different than saying you don't care about free speech because you have nothing to say.
-Edward Snowden

You access the service at ybin.me.


Everybody has a right to privacy. Ybin has been created with a simple idea in mind. It’s a simple pastebin where you can paste anything privately with a simple to use, purely minimalistic user interface and no complicated options.


Ybin is based on the work of wonderful developer(s) behind an open-source encrypted pastebin project called ZeroBin (thank you). Most of the encryption algorithms used on ybin are taken directly from ZeroBin without modifications.

The code

I can talk all I want about how private the service is, and how it works, but without the source code, those are just words with no meaning. Ybin is, of course, open-source and you can check out the full code on my github repository. Contributions are also more than welcome.


All data you paste through ybin is encrypted with AES256, which is borderline impossible to crack by bruteforcing. Check the following link to get a better idea. In short, exhausting half of the AES256 keyspace using resources we don’t yet have would take more time than the age of our beloved Universe.

Encryption is done solely on the client side, using an open-source sjcl JavaScript encryption library. When you submit a paste, sjcl generates a random encryption key and encrypts pasted data with AES256 using that key. Then, it send the cipher to the server and redirects you to the paste page and appends the key to the URL, after the # symbol. Since everything is done on the client side, your data is only transmitted to the server in encrypted form (pure cipher), meaning both the original data you’ve pasted, and the generated key are completely private. The server only stores cipher data. So, reading or decrypting your data is completely impossible on my side, since I have no way to find out the key. This grants ybin plausible deniability (in theory), since I can’t moderate data I can’t read or decrypt.


  • Information provided by your browser (including your IP address) is never stored on the server. All server logs are configured to go directly to /dev/null. Take a look at the following snippet from the nginx configuration file:
    server_name ybin.me;
    access_log /dev/null main;
    error_log /dev/null;
  • No metadata is stored when you submit a paste (including timestamps).
  • Ybin has no tracking JavaScript code from Google and/or other services. Also, it has no ads that could track you.
  • Robots.txt disallows search engine crawlers to crawl and index pastes. Of course, this guarantees nothing since most of them ignore robots.txt anyway.
  • It's only accessible through SSL. (thanks for the feedback, reddit)


Now, this is the main question. Is this service completely safe? Well, I have to disappoint you, it’s not. Since all of the encryption is done by a JavaScript library, modifying the library from the outside can weaken or annul the encryption (like in MITM attacks). JavaScript is not safe, period. But, it’s a lot safer then transmitting raw data or keys to the server, nonetheless.


Let's take a look at the following link: http://ybin.me/p/4eed1e530abe8348#aWImxYyjpqd62atEr1T9AP6rvHnO0vB1cvYvgifGmyM=.
First of all, you can see that the key is aWImxYyjpqd62atEr1T9AP6rvHnO0vB1cvYvgifGmyM=, extracted from the URL.
When you visit the link, you'll see the following pasted data:

Hello to zx readers from ybin!

But, the only data on the server of this paste is this:


Ybin does not, in any way, guarantee complete privacy and absolutely unbreakable encryption (as stated in Safety paragraph) while using the service. But, it tries to achieve the best possible privacy by using best practices.

DroidDucky - Can an Android quack like a duck?


In this article, I’m going to present a way to perform Keystroke Injection attacks from a plain Android device. A keyboard is the main way of communicating between the user and the computer. Because of this special connection, computers always trust keyboards. Keystroke Injection takes advantage of this inherent trust. In short, whenever you connect a device claiming to be a keyboard, a computer will automatically recognize it and accept, without a doubt. How can a device claim to be a keyboard? Simple, using a universal specification called HID (Human Interface Device). It just has to enumerate itself as a Keyboard HID, and that’s it.

Have you ever heard of USB Rubber Ducky? It’s a quite simple and lovely piece of hardware that does just what I’ve described in the paragraph above. It quacks like a keyboard, so it must be a keyboard. You can check it out (or even purchase it) here.
Why is USB Rubber Ducky interesting for the sake of this article? It has a nice and simple scripting language (duckyscript), a big community, and lots of already written payloads.

In this article, I’ll explain how Android device can act as a keyboard, how to install the required driver, and how to use DroidDucky to execute duckyscript payloads. DroidDucky is a duckyscript interpreter written in Bash which brings all of ducky scripting goodness to Android. Also, I’ll provide some details of DroidDucky implementation.

Android device as a HID Keyboard?

Turning an Android device into a HID keyboard (or a mouse, or even a joystick) is possible because of the great developer(s) of an open-source driver called android-keyboard-gadget. The driver adds two new devices called /dev/hidg0 (keyboard) and /dev/hidg1 (mouse) which accept raw keyboard/mouse events and can be easily used with standard system calls. The nicest thing, of course, is that it emulates a HID so neither drivers nor installations are necessary on the computer. It can be used even in BIOS and bootloader mode. It’s truly plug and play. Since it’s a custom driver, it has to be embedded in the kernel, and, unfortunately, not all Android devices are supported out-of-the-box yet. Guides on compiling, embedding and using a custom kernel are available on the project page as well, and so is a list of currently supported devices. Just a thing to note, installing a custom kernel usually requires unlocking your device’s bootloader and rooting, so it’ll probably void your warranty.

Using the driver

The basic idea would be to send raw keyboard/mouse events to newly created devices using write() system call. Fortunately, android-keyboard-gadget project also provides a lovely little utility called hid-gadget-test that supports scripting and makes the usage a whole lot easier. The DroidDucky duckyscript interpreter I’m using is a wrapper around this utility.

The interpreter


DroidDucky is just a simple Bash script. The syntax is based on duckyscript’s documentation and it should be fully compatible with duckyscript codes, even with some undocumented features. I’ve personally tried a couple of payloads available online and it worked without an issue. The list of supported commands and a basic usage tutorial can be found here. (courtesy of hak5darren)

Developing a full Android application based on DroidDucky to simplify the whole process is a possibility I’m currently working on.

Payload files

A file that contains payload code must have Unix line endings, otherwise the script can get buggy. In fact, if it is buggy, this is the first thing to check. Extension of the payload files is not important.


In order to use DroidDucky you have to have some kind of Android terminal emulator application. Lots of them can be found on the Play Store (both free and paid). I’m currently using JuiceSSH, and I can recommend it.

Syntax is quite simple. Just run droidducky.sh with payload file name as the first argument. Make sure that droidducky.sh has execution permission.


bash droidducky.sh payload.dd


DroidDucky is, of course, an open-source project. The whole code can be accessed at my github repository.


Payload code:

REM Loading payload code.
REM Opening command prompt.
REM Sending the message.
STRING Hello World! I'm in guys.

Running the payload

Command prompt open

Edit: Video demonstration


How many times have you seen a computer with a user logged in with no one around? I’m guessing a lot. The possibilities are just endless. Whether is it just playing a prank on your friends like changing their background or rebooting their PC, to running reverse shells or meterpreter. It’s really up to you. Plug in the USB, start the payload and, with typing speed only limited by USB cable’s bandwidth (more than 1000 words per minute), you’ll be done in no time. You can find lots of payloads here. Other resources are available online.


Please note that this article does not, in any way, support illegal activities while using DroidDucky.

Once you go functional, you can never go back


Being an imperative (procedural, object-oriented), von Neumann style programmer for many years now, I thought there was nothing better out there. Few months ago, I came across a new paradigm (to me, at least) called functional programming. Ever heard of LISP? I instantly liked it. Of course, I still do most of my work in imperative languages, but, slowly, I'm making the switch, at least for simpler programs. In this article, I will give you a small theoretical introduction to functional programming and state some arguments on why I think functional programming is, in some aspects, better than imperative. There are, of course, aspects, where imperative programming is unbeatable, and I will try to cover those too. I will not focus on only one language, but two a lil' bit different functional languages called Scheme (LISP dialect) and Haskell (mainstream functional language with a lot of potential). Some features may not be available in both.

Introduction to functional programming

Functional programming languages fall under the declarative languages category, meaning algorithms are written in form of relations between steps, not step by step, as in imperative style. Let's take a look at the following example, to make it clear.

Fibonacci sequence in C++
#include <iostream>

using namespace std;

int main() {
	int num = 0;

	cin >> num;

	int i = 0;

    unsigned long a = 1;
    unsigned long b = 0;

    unsigned long fib = 0;

    while(i++ < num) {
    	b = fib;

        fib = a + b;
        cout << fib << endl;

        a = b;
	return 0;

Fibonacci sequence in LISP-oid Scheme
(define (fib n)
	   ((= n 0) 0)
	   ((= n 1) 1)
	   (else (+ (fib (- n 1)) (fib (- n 2))))

Please note that Scheme implementation is a lot worse complexity-wise than it's C++ counter-part. You should never use pure recursion in this form as it's time complexity is exponential, O(2^n) in worst-case scenario. This is just an example of simple notation. It's complexity can be improved a lot (reaching C++) by accumulating values and passing them through recursive calls.

As you can see, notation in functional languages is much closer to classic mathematical notation.

Functional languages (FL) features

In order to call a language purely functional, it has to have 6 distinct features. I will give a short description about each.

Edit: I, in no way, claim that all functional languages have these 6 features. The features of functional programming languages are referenced from a book called "Introduction to Scheme". These are the feature FLs should posess, but, usally, that's not the case (not even in my examples, Scheme and Haskell).

Lazy evaluation and non-strict semantics

Lazy eval, for short, is one of the most important features of pure FL. Basically, nothing is calculated/evaluated until it's really required. If it's not required, it will not be calculated at all, simple as that. Sounds quite logical, don't you think? Lazy eval allows lovely things like creation of infinite structures (i. e. list of cardinals) and frees the programmer from lots of unnecessary if clauses.

In pure FL, all operators and all evaluations are non-strict, meaning that an operator can succeed even if one of it's operands is not initialized and is not needed. This happens because of the previously described lazy eval feature. This is usually present in most imperative languages as well (&&, || operators in C-like languages). The difference is that, every expression in FL is non-strict, not just logic operators.

Functions as first class citizens

Functions in FL are just like any other data/objects. They can be passed to other functions as parameters, they can be return values of functions and they can be a part of any data structure (tuple, list). This allows creation of higher-order functions (functions that manipulate other functions).

No side effects

Side effects that are possible in a lot of imperative languages are nonexistent in FL. That's also quite logical, when you think about it. In mathematics, f(x) is always equal to f(x), so why not make it so in programming, as well? Controlled side effects are possible in some FL.

Static binding

All variables are allocated at compile time and are statically bound. No need to go into more details.

No explicit flow control

As I've said in the beginning, writing an algorithm in a FL, is not a matter of writing it step by step, line by line, but rather determining relations. Therefore, you can't directly control the program flow, as it's not just from top to bottom. Controlling the flow is only possible through function calls/expression evaluation.

No commands/procedures

Everything in FL is an expression and should be treated that way. Even the whole program itself is just an expression. An expression that needs to be evaluated. Therefore, there are no explicit procedures, just pure expressions. Since the program is an expression, it's execution is just expression evaluation.

The only one important thing left to say is that FL are based on Lambda calculus by Church. Going into details about it is not the point of this article, but it's and interesting read, and I recommend it.

Enough of theory, let's get to the point.

The pros


The thing that I most adore about FL is that algorithms are usually a lot shorter and a lot more elegant. Shorter codes with less typing imply better productivity.


As you've seen in an example above, notation in is very close to classic mathematical notation. This is actually a nice thing (in my opinion), because it enables you to implement algorithms directly from their definition. Let's take a look at a merge sort algorithm written in Scheme, and in Haskell.

MS in Scheme
(define (mergesort x)
  (if (= 0 (length x))
      (if (= (length x) 1)
          (combine (mergesort (firstHalf x (/ (length x) 2))) (mergesort (lastHalf x (/ (length x) 2)))
(define (combine list1 list2)
  (if (null? list1) list2
      (if (null? list2) list1
          (if (<= (car list1) (car list2))
              ;car of list 1 is second element of list 2
              (cons (car list1) (combine (cdr list1) list2))
              (cons (car list2) (combine list1 (cdr list2)))
(define (firstHalf L N)
  (if (= N 0)
  (if (or (= N 1) (< N 2)) 
      (list (car L))
      (cons (car L) (firstHalf (cdr L) (- N 1)))))
(define (lastHalf L N)
  (if (= N 0) L); Base Case
  (if (or (= N 1) (< N 2))
      (cdr L)
      (lastHalf (cdr L) (- N 1)))

MS in Haskell
sort :: Ord a => [a] -> [a]
sort []         =  []
sort [x]        =  [x]
sort xs         =  merge (sort ys) (sort zs)
  where (ys,zs) = split xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
      | x<=y      = x : merge xs (y:ys)
      | otherwise = y : merge (x:xs) ys
split []        =  ([], [])
split [x]       =  ([x], [])
split (x:y:xs)  =  (x:l, y:r)
  where (l, r)  =  split xs

As you can see, we can follow the definition directly (split the list in two, sort both halves, merge both halves). Implementation of such algorithm in an imperative language requires a lot more work, and the code is a lot less elegant.

MS in C++
void merge(int a[], const int low, const int mid, const int high)
        // Variables declaration. 
        int * b = new int[high+1-low];
        int h,i,j,k;
        // Merges the two array's into b[] until the first one is finish
        // Completes the array filling in it the missing values
        // Prints into the original array
        delete[] b;
void merge_sort( int a[], const int low, const int high )               // Recursive sort ...
        int mid;
        if( low < high )
                mid = ( low + high ) / 2;
                merge_sort( a, low, mid );
                merge_sort( a, mid + 1, high );
                merge( a, low, mid, high );

* Algorithms were taken from wikibooks.org

Pattern matching (Haskell only)

Instead of writing a lot of ifs for different situations, we can just use pattern matching and let the language determine which one to use. The example below shows how easy it is to use it.

List reverse in Haskell
reverse :: [a] -> [a]
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]

ZF expressions (Haskell only)

ZF expression (introduced in KRC) are one of my favorite features. ZF stands for Zermelo-Fraenkel, based on their set theory. ZF expressions basically allow programmers to use set notation used in mathematics. Let's take a look at the quick sort algorithm implemented with ZF expressions.

qs []    = []
qs [x]    = [x]
qs (x:xs) = quick [ u | u <- xs, u < x ] ++ [x] ++ quick [ u | u <- xs, u >= x ]

Woah, only three lines? How many lines can you get in an imperative language? Take a look below, it is a lot longer.

void qsort(int a[], int lo, int hi) {
  int h, l, p, t;

  if (lo < hi) {
    l = lo;
    h = hi;
    p = a[hi];

    do {
      while ((l < h) && (a[l] <= p)) 
      while ((h > l) && (a[h] >= p))
      if (l < h) {
          t = a[l];
          a[l] = a[h];
          a[h] = t;
    } while (l < h);

    a[hi] = a[l];
    a[l] = p;

    qsort(a, lo, l-1);
    qsort(a, l+1, hi);

Something similar can be achieved in Scheme as well using filter higher-order function.

(define (qs l)
  (if (null? l)
      (append (qs (filter (lambda (x) (<= x (car l))) (cdr l))) (list (car l)) (qs (filter (lambda (x) (> x (car l))) (cdr l))))

Mistake chance reduction

Since there's no real flow control and no real variables, chance of producing errors converges to zero. Also, the chance is reduced by eliminating side effects.

Different problem solving way

Solving problems in FL is, in some way, easier than in imperative, mostly because of the possibility of purely mathematical notation. This, of course, is rather personal, and should be taken as both a pro and a con, since it can be either of that, depending on the programmer.

Lambda functions

Lambda functions are getting more and more attention in imperative programming as well nowadays. For example, they were reintroduced in Java 1.8. Lambda functions/expressions are, simply said, small functions (rarely, they can be big) without a name. Their best application is inline usage, where defining a separate function would be an unnecessary thing to do. The following example shows how it's defined.

Lambda in Scheme
(lambda (x y) (+ x y y)) ; (f(x, y) = x+y+y

Lambda in Haskell
 x y -> x + y + y

As I've said, lambdas are also available in Java.
Lambda in Java
(x, y) -> { return x + y + y };

Higher-order functions

As described above, higher-order functions are used to manipulate other functions. They can take functions as parameters, and they can return functions as well. Depending on implementation, in some FL, all functions are Curry's, and in some you have to define them as Curry's. Some popular examples are Map and Reduce (by Reduce, I'm referring to foldr) functions.

Map in Scheme
(define (map f l)
  (if (null? l)
      (cons (f (car l)) (map f (cdr l)))

Map in Haskell
map :: (a -> b) -> [a] -> [b]  
map _ [] = []  
map f (x:xs) = f x : map f xs

Reduce in Scheme
(define (reduce f b l)
  (if (null? l)
      (f (car l) (reduce f b (cdr l)))

Reduce in Haskell
foldr f z []     = z 
foldr f z (x:xs) = f x (foldr f z xs) 

Since this is impossible in imperative languages, I can't give you a comparison.

Edit: After publishing this article, it was brought to my attention that I was purely wrong on this one. These are possible in most imperative languages as well, yet they are not used so often. I apologize.

The cons

Everything has its bad sides, that's just how it is. Let's go on through some of the most prominent.

No iteration

In FL, everything is achieved by using recursion and there's no iteration in any kind (at least it shouldn't be). This can be a problem for an imperative programmer. Letting go of loops may be the harder thing for me. Some things are just harder to solve only with recursion.

No flow control

Even though I talked about this as a pro, it's also a con. Having no control over the program flow can sometime make you feel rather limited.


Even though functional languages may not be applicable to everything, it's still a fun paradigm to learn and I recommend it. I'm not, in any way, saying that you should give up everything you know and switch, as that's not something that I'm willing to do either. I'm saying that for simpler algorithms, programming in functional paradigm can make you a lot more productive by eliminating some of the bad elements of imperative style.

Edit: After publishing the article, it received lots of negative thoughts. I just want to say, that this is not an anti-imperative post. I, myself, am an imperative programmer and I'm not giving up imeprative style for functional. The whole point of this article was a small theorethical introduction to functional languages and functional programming with some examples of interesting features unavailable/rarely used in imperative style. I, once again, apologize for the couple of mistakes I've made.