GithubHelp home page GithubHelp logo

pk-fr / yakpro-po Goto Github PK

View Code? Open in Web Editor NEW
1.2K 40.0 340.0 198 KB

YAK Pro - Php Obfuscator

Home Page: http://www.php-obfuscator.com

License: Other

PHP 100.00%
php obfuscation php-obfuscator obfuscator

yakpro-po's Introduction

Cette page en Français

YAK Pro - Php Obfuscator

YAK Pro stands for Yet Another Killer Product.

Free, Open Source, Published under the MIT License.

This tool parses php with the best existing php parser PHP-Parser 4.x, which is an awesome php parsing library written by nikic.

You just have to download the zip archive and uncompress it under the PHP-Parser subdirectory, or make a git clone ...

Warning:

yakpro-po 2.x works on PhpParser 4.x   
it will run on php >= 7.0, obfuscating code for php 5.2 to php 7.3   

If you are running php 5.3 or higher,  
Please use unsupported [yakpro-po 1.x](https://github.com/pk-fr/yakpro-po/tree/1.x) which works on 1.x branch of PhpParser.   

The yakpro-po.cnf self-documented file contains many configuration options! Take a look at it!

Demo : yakpro-po demo.

Prerequisites: php 7.0 or higher, PHP-Parser 4.x.

Note: This tool has been written in order to obfuscate pure php sources. it is not intended to be used with html and embeded php inside (use at your own risks...you may try to deactivate statements shuffling...). You can still embed html within php using the echo <<<END ... END; syntax!

What is Php Obfuscation?

When you have a php project you want to distribute, as php is a script interpretor, you distribute also all the sources of your software!

You may want, for any reason, that other people do not understand, modify, or adapt your software.

As your software must be understandable by the php runtime, but needs to be very difficult to understand by human people, obfuscation is a very good way to achieve this goal.

YAK Pro - Php Obfuscator Obfuscation Main Features:

  • Removes all comments, indentation, and generates a single line program file.

  • Obfuscates if, else, elseif, for, while, do while by replacing them with if goto statements.

  • Obfuscates string literals.

  • Scrambles names for:

    • Variables, Functions, Constants.
    • Classes, Interfaces, Traits.
    • Properties, Methods.
    • Namespaces.
    • Labels.
  • Shuffles Statements.

  • Recursivly obfuscates a project's directory.

  • Makefile like, timestamps based mechanism, to re-obfuscate only files that were changed since last obfuscation.

  • Many configuration options that let you have full control of what is obfuscated within your project!

Why Yet Another Php Obfuscator?

I began testing some already existing php obfuscation tools, but I did'nt find one that was fitting all my needs. I wanted a simple command line tool, based on a highly customisable config file, that would be able to:

  • Be fast and re-obfuscate only files that were changed based on timestamps of files.
  • Preserve some files and/or directories from obfuscation.
  • Not include in the obfuscated target, some files/directories that are present on the source project.
  • Accept lists of names and/or name prefixes to not obfuscate.

So I started to write this tool. Version 1.0 has been written within a few days...

Setup:

Note: This setup is also valid for Windows 10 Anniversary with bash installed...  
1. Prerequisites: git and php-cli (command line interface) packages. 
   on ubuntu: (adapt according your linux distribution) 
   # apt install git 
   # apt install php-cli
   do not forget to install all other php modules that you are using within your software:
        for example: apt install php-mysql if you are using mysql... 
2. Navigate to the directory where you want to install yakpro-po (/usr/local is a good idea): 
   # cd /usr/local 
3. Then retrieve from GitHub: 
   # git clone https://github.com/pk-fr/yakpro-po.git 
4. Go to the yakpro-po directory: 
   # cd yakpro-po 
5. Then retrieve from GitHub: 
   # git clone https://github.com/nikic/PHP-Parser.git --branch 4.x
6. Check that yakpro-po.php has execute rights, otherwise:
                                        # chmod a+x yakpro-po.php 
7. Create a symbolic link in the /usr/local/bin directory
   # cd /usr/local/bin 
   # ln -s /usr/local/yakpro-po/yakpro-po.php yakpro-po 
8. You can now run yakpro-po 
   # yakpro-po --help 
   # yakpro-po test.php 

Modify a copy of the yakpro-po.cnf to fit your needs...
Read the "Configuration file loading algorithm" section of this document
to choose the best location suiting your needs!

That's it! You're done!

Usage:

yakpro-po Obfuscates according configuration file! (See configuration file loading algorithm)

yakpro-po source_filename Obfuscates code to stdout

yakpro-po source_filename -o target_filename Obfuscates code to target_filename

yakpro-po source_directory -o target_directory Recursivly obfuscates code to target_directory/yakpro-po (creates it if it does not already exist).

yakpro-po --config-file config_file_path According to config_file_path.

yakpro-po --clean Requires target_directory to be present in your config file! Recursivly removes target_directory/yakpro-po

Configuration file loading algorithm:

(the first found is used)

--config-file argument value
YAKPRO_PO_CONFIG_FILE environment variable value if existing and not empty.

filename selection:
       YAKPRO_PO_CONFIG_FILENAME environment variable value if existing and not empty,
       yakpro-po.cnf otherwise.

 file is then searched in the following directories:
        YAKPRO_PO_CONFIG_DIRECTORY  environment variable value if existing and not empty.
        current_working_directory
        current_working_directory/config
        home_directory
        home_directory/config
        /usr/local/YAK/yakpro-po
        source_code_directory/default_conf_filename

  if no config file is found, default values are used.

  You can find the default config file as an example in the yakpro-po.cnf file of the
  repository.
  Do not modify it directly because it will be overwritten at each update!
  Use your own yakpro-po.cnf file (for example in the root directory of your project)

  When working on directories,
  context is saved in order to reuse the same obfuscation translation table.
  When you make some changes in one or several source files,
  yakpro-po uses timestamps to only reobfuscate files that were changed
  since the last obfuscation.
  This can save you a lot of time.

  caveats: does not delete files that are no more present...
           use --clean  command line parameter, and then re-obfuscate all!

Other command line options:

(override config file settings)

--silent                            do not display Information level messages.
--debug                             (internal debugging use) displays the syntax tree.

-s or
--no-strip-indentation              multi line output
--strip-indentation                 single line output

--no-shuffle-statements             do not shuffle statements
--shuffle-statements                       shuffle statements

--no-obfuscate-string-literal       do not obfuscate string literals
--obfuscate-string-literal                 obfuscate string literals

--no-obfuscate-loop-statement       do not obfuscate loop statements
--obfuscate-loop-statement                 obfuscate loop statements

--no-obfuscate-if-statement         do not obfuscate if statements
--obfuscate-if-statement                   obfuscate if statements

--no-obfuscate-constant-name        do not obfuscate constant names
--obfuscate-constant-name                  obfuscate constant names

--no-obfuscate-variable-name        do not obfuscate variable names
--obfuscate-variable-name                  obfuscate variable names

--no-obfuscate-function-name        do not obfuscate function names
--obfuscate-function-name                  obfuscate function names

--no-obfuscate-class_constant-name  do not obfuscate class constant names
--obfuscate-class_constant-name            obfuscate class constant names

--no-obfuscate-class-name           do not obfuscate class names
--obfuscate-class-name                     obfuscate class names

--no-obfuscate-interface-name       do not obfuscate interface names
--obfuscate-interface-name                 obfuscate interface names

--no-obfuscate-trait-name           do not obfuscate trait names
--obfuscate-trait-name                     obfuscate trait names

--no-obfuscate-property-name        do not obfuscate property names
--obfuscate-property-name                  obfuscate property names

--no-obfuscate-method-name          do not obfuscate method names
--obfuscate-method-name                    obfuscate method names

--no-obfuscate-namespace-name       do not obfuscate namespace names
--obfuscate-namespace-name                 obfuscate namespace names

--no-obfuscate-label-name           do not obfuscate label names
--obfuscate-label-name                     obfuscate label names

--scramble-mode     identifier|hexa|numeric         force scramble mode
--scramble-length   length ( min=2; max = 16 for scramble_mode=identifier,
                                    max = 32 for scramble_mode = hexa or numeric)

--whatis scrambled_name             retrieves original symbol from obfuscation context.
                                    (usefull for debugging your code when you give away
                                    obfuscated code, and keep the same obfuscation context).
                                    Tip: do not include the $ symbol, or use \$ because
                                    $ has special meaning in shell.

-h or
--help                              displays help.

YOU MUST BE AWARE OF THE FOLLOWING:

If your obfuscated software makes use of external libraries
that you do not obfuscate along with your software:

if the library consists of functions:
        set the $conf->obfuscate_function_name to false in your yakpro-po.cnf config file,
        or declare all the functions names you are using in $conf->t_ignore_functions
        example : $conf->t_ignore_functions = array('my_func1','my_func2');

if the library consists of classes :
        set the $conf->obfuscate_class_name,
                $conf->obfuscate_property_name,
                $conf->obfuscate_method_name
        to false in your yakpro-po.cnf config file...
        ... or declare all the classes, properties, methods names you are using in
                $conf->t_ignore_classes,
                $conf->t_ignore_properties,
                $conf->t_ignore_methods.

This is also true for PDO::FETCH_OBJ that retrieves properties from external source
(i.e. database columns).

Hints for preparing your Software to be run obfuscated

At first you can test obfuscating only variable names...


If you obfuscate functions, do not use indirect function calls like
    $my_var = 'my_function';
    $my_var();
or put all the function names you call indirectly in the $conf->t_ignore_functions array!


Do not use indirect variable names!
    $$my_var = something;
or put all the variable names you use indirectly in the $conf->t_ignore_variables array!


Do not use PDO::FETCH_OBJ  but use PDO::FETCH_ASSOC instead!
or disable properties obfuscation in the config file.


If you use the define function for defining constants, the only allowed form is when the
define function has exactly 2 arguments, and the first one is a litteral string!
You MUST disable constants obfuscation in the config file, if you use any other forms
of the define function!
There is no problem with the const MY_CONST = something; form!

Performance considerations

Except for the statements shuffling obfuscation option,
the obfuscated program speed is almost the same than the original one.

$conf->shuffle_stmts    is set to true by default.

If you encounter performance issues, you can either set the option to false,
or fine tune the shuffle parameters with the associated options.

You must know that the lesser the chunk size, the better the obfuscation,
and the lower your software performance!

(during my own tests, the maximum of obfuscation costs me about 13% of performance)

You can tune it as you wish!

Known Issues

segmentation fault

opcache crashes on Ubuntu 21.10 - php 8.0.8 (segfault) both within apache2 and cli when
shuffle-statements is turned on for big files

works perfectly with newer versions of php (8.0.16 8.1 )

sedimentation-fault reported on issue #75 that a segmentation fault could occure in php's garbage collector when obfuscating many big files in a project:

Trying to obfuscate ~5000 PHP files of ~1000 lines each, yakpro-po stopped after processing ~1600 files 
with a simple (and frustrating) Segmentation fault

Workaround:

There is a stack overflow in garbage collector. The solution is to increase limit for stack.
To see your current limit, type

ulimit -s

I had 8192 - for a task of this size obviously totally undersized...
Change this to something more appropriate, say

ulimit -s 102400

and retry - the segmentation fault is gone! :-)

yakpro-po's People

Contributors

pk-fr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yakpro-po's Issues

obfuscating and how to proof if the code is 100% running

Hey i like your obfuscating repository.
I am a wordpress plugin developer and i like to secure my code.
My biggest challange is to get the code 100% running after obfuscating.

Is there a syntax check before obfuscating?
to check if the output is still working?
i use IonCube loaders/coding at the moment which checks the code before coding.
But this needs to habe the IonCube loaders installed on server.

How do you check your work after obfuscating?

File permissions not kept on obfuscated files

I ran the obfuscator on a project that has a bin folder with a few executable files but they lost the execution bit. It would be nice if the obfuscator kept the same permissions for the files.

Issue with symphony Annotations

Hi,
Is there some way to ignore or validate symphony (framework) annotations?
I work on symphony and php-obfuscator remove them from the source code. What can i do in such case?

Thanks in advance

Problem with use of eval

Hi guy,
first of all thank you for your work.

I have a problem and hope you can help me.

I use the eval functions in some place of my code and when I try to obfuscate it doesn't word:

`<?php

function funcTest($param)
{
return "hey! " . $param;
}

$sFuncToCall = "funcTest";
$sParam = "hello world";
eval("$sReturnFunction = " . $sFuncToCall . "("" . $sParam . "");");

echo $sReturnFunction;

?>`

and here you can find obfuscated version:

`<?php

function funcTest($A92PuKiSftPYqqd)
{
return "\150\x65\171\x21\x20" . $A92PuKiSftPYqqd;
}
$ZvHkE9gCbvdtEZE = "\x66\x75\x6e\143\x54\x65\163\x74";
$JNc7kjLDMCgghbp = "\x68\x65\x6c\x6c\x6f\40\x77\157\x72\x6c\x64";
eval("\x24\x73\x52\x65\x74\165\x72\x6e\106\165\156\x63\x74\151\x6f\156\x20\x3d\x20" . $ZvHkE9gCbvdtEZE . "\x28\x22" . $JNc7kjLDMCgghbp . "\42\x29\73");
echo $HvGn14hkJPjuMtz;

?>`

Catch block class names are not scrambled

Test case:

<?php
class FooException extends Exception { }
try {
    echo "foo ";
    throw new FooException;
}
catch (FooException $foo) {
    echo "bar\n";
}

Example output:

<?php

class N0VHa extends Exception
{
}
try {
    echo "\146\157\157\x20";
    throw new N0vHa();
} catch (FooException $b0p6v) {
    echo "\142\x61\162\12";
}

FooException should have been replaced by N0VHa for the above example to work.

Allow new(...) as a method

Hi,

since since PHP 7.0 the expression new is no longer reserved, so it can also be used as function names, it would be desirable if you consider this in the next update.

There are some third party libs that use this expression. Would be a great feature.

Code shuffler moves use keyword after class instantiation

Test case:

<?php
echo "a";
use FooNamespace\BarClass;
echo "b";
BarClass::foo();
echo "c";
echo "d";
echo "e";

Example obfuscated output:

$ yakpro-po --silent --shuffle-statements --no-obfuscate-namespace-name --no-obfuscate-class-name --no-obfuscate-string-literal testScramblerUse.php
<?php
 goto eRjJL; eRjJL: echo 'a'; goto bMybk; jYOQK: echo 'c'; goto RLpd3; s61kw: echo 'b'; goto N2256; N2256: BarClass::U_97n(); goto jYOQK; RLpd3: echo 'd'; goto V30rC; bMybk: use FooNamespace\BarClass; goto s61kw; V30rC: echo 'e';

While the order of execution is correct, PHP actually does not execute the use statement, but interpret it statement-by-statement while generating bytecode for the function. It will select the wrong class for the bytecode and everything will go haywire.

For the sake of completeness, here is a test class which will show that the above code indeed does not run properly. Add an include line for it right after the <?php of each code snippet.

// BarClass.php
<?php
namespace FooNamespace;
class BarClass {
  public static function foo() {
    echo "foo";
  }
}

Use keyword is not processed correctly

Test case:

<?php
use FooNamespace\BarClass;
BarClass::fooMethod();

Example output:

<?php
 use Ursex\edPAQ as eDpAq; lhk21::n0Qum();

I would have expected the obfuscator to emit eDpAq::n0Qum(); as function call instead. Some implementation for aliasing classes appears to be there already since an 'as' is appended to the 'use' statement, but it doesn't do the right thing just yet.

Undefined function directory_remove

In includes/functions.php there are references to a directory_remove function which doesn't exist in PHP. Is it supposed to be rmdir? I'm not sure if that one is recursive or not.

extract function

Do you have idea to make the code run as expected after Obfuscation?


/* Suppose that $var_array is an array returned from
wddx_deserialize */

$size = "large";
$var_array = array("color" => "blue",
	"size" => "medium",
	"shape" => "sphere");
extract($var_array, EXTR_PREFIX_SAME, "wddx");

echo "$color, $size, $shape, $wddx_size\n";

Newbie.. PHP parser no correctly installed

Hi, I installed PHP-Parser as indicated at xampp\parser\ folder vía composer. I extracted yakpro-po.zip in that folder as directed but seems not to work. ¿How can I get it done? I'm running windows 8.

Bug: Function definition in "parse" time instead of execution time

If I have this code:

a.php:

function f() {
  echo 'test';
}
include('b.php');

b.php:

if (!function_exists('f')) {
   function f() {
       echo 'test2';
   }
}

When the option shuffle_stmts is enabled, the definition of f() in b.php will be appear out of the if, therefore the php interpreter will try to define the function in "parse" time instead of execution time, and this will throw the error below:

PHP Fatal error:  Cannot redeclare f() in b.php on line 2

Maybe we can just add an if (true) in these situations.

Class constant reference using self keyword is not processed correctly

Hey, I've been testing your obfuscator (and it's awesome so far.) I stumbled over a few minor issues and will open a report to track the status for each.

Test case:

<?php
class Test {
    const FOO = 'BAR';
    static public function printFoo() {
        echo self::FOO;
    }
}

Example obfuscated output:

<?php
class VTMys
{
    const tbLwc = "\x42\101\x52";
    public static function X09pB()
    {
        echo self::FOO;
    }
}

The obfuscated code will not run because self::FOO was not replaced by self::tbLwc.

Obfuscate project with composer autoload

Hi, Pascal! First of all - thanks a lot for YAK Pro, it's the best php obfuscator, I saw on github.

Need some help to work it out with my current project, that use composer autoload https://getcomposer.org/doc/01-basic-usage.md#autoloading

Before obfuscation:
vendor/composer/autoload_real.php

class ComposerAutoloaderInitcef6ac477e716f5e193a43f09eb4d6a4
{
    private static $loader;
    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }
        spl_autoload_register(array('ComposerAutoloaderInitcef6ac477e716f5e193a43f09eb4d6a4', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        spl_autoload_unregister(array('ComposerAutoloaderInitcef6ac477e716f5e193a43f09eb4d6a4', 'loadClassLoader'));

After obfuscation
vendor/composer/autoload_real.php

class It72Z
{
    private static $nCiZ5;
    public static function BYb7h($FP2VQ)
    {
1        if ('Composer\\Autoload\\ClassLoader' === $FP2VQ) {
            require __DIR__ . '/ClassLoader.php';
        }
    }
    public static function b80JC()
    {
        if (null !== self::$nCiZ5) {
            return self::$nCiZ5;
        }
2        spl_autoload_register(array('ComposerAutoloaderInitcef6ac477e716f5e193a43f09eb4d6a4', 'loadClassLoader'), true, true);
        self::$nCiZ5 = $r2XDu = new \I_myr\xeXKb\z2cFF();
        spl_autoload_unregister(array('ComposerAutoloaderInitcef6ac477e716f5e193a43f09eb4d6a4', 'loadClassLoader'));

It need's to be:

1 if ('I_myr\xeXKb\z2cFF' === $FP2VQ) {
2 spl_autoload_register(array('It72Z', 'BYb7h'), true, true);

and so on. When I corrected this file myself and go deeper - there are more errors like this in files, that are automatic generated by composer.

So my question is - Did you try to obfuscate projects, that use composer? If yes, what settings I need to make in yakpro-po.cnf to make it work? Maybe add some standard composer classes in t_ignore_pre_defined_classes?

Thanks!

Fatal error: Uncaught Error

I'm trying to obfuscate a small PHP file, I've tried to obfuscate the file with demo version too, same error happend.
error:
Fatal error: Uncaught Error: Class 'NwCfO' not found in C:\laragon\www\bings.php:8 Stack trace: #0 {main} thrown in C:\laragon\www\bings.php on line 8
here's the original PHP file:

header('Content-type: text/html; charset=UTF-8');
require_once 'bing.php';
$search = new bing_api("help");
$search->setDork('خرید گوشی');
$search->setCount(50);
// number of results on each page
$search->setSubLinks(TRUE);
// returns sublinks of the results if available

$search->search();
// start the search & extract the data
$descs = $search->getDescs(); // return the results ( title & link )
foreach($descs as $desc){
	echo $desc . '<br/>';
}
?>

here's the obfuscated file :

/*   __________________________________________________
    |  Obfuscated by YAK Pro - Php Obfuscator  2.0.5   |
    |              on 2019-09-24 13:00:30              |
    |    GitHub: https://github.com/pk-fr/yakpro-po    |
    |__________________________________________________|
*/
 goto Zq88w; iS_Nq: require_once "\142\x69\156\x67\x2e\x70\x68\160"; goto gZ8oc; sQPBr: $Kb1mk->f3vBK("\xd8\256\330\xb1\333\214\xd8\xaf\40\xda\xaf\331\x88\330\264\333\214"); goto vzuVl; vcz_5: $Kb1mk->fChB7(TRUE); goto EHnDU; vzuVl: $Kb1mk->ZaHhl(50); goto vcz_5; ooGUt: $zm0lC = $Kb1mk->Mrf1c(); goto B1J2f; gZ8oc: $Kb1mk = new NwCfO("\x68\145\x6c\x70"); goto sQPBr; EHnDU: $Kb1mk->SAK6J(); goto ooGUt; B1J2f: foreach ($zm0lC as $hHKnC) { echo $hHKnC . "\74\x62\162\57\x3e"; gKF5w: } goto IpRf8; Zq88w: header("\103\157\x6e\164\145\x6e\x74\x2d\x74\171\x70\x65\72\x20\164\145\x78\x74\x2f\x68\x74\155\x6c\73\x20\143\150\x61\x72\163\145\164\75\125\x54\x46\x2d\70"); goto iS_Nq; IpRf8: c3txC:

here's the config file, just changed this line:
$conf->parser_mode = 'ONLY_PHP7';

// YAK Pro - Php Obfuscator: Config File
// Do not delete the previous line! it's a magic string for config file!
//========================================================================
// Author:  Pascal KISSIAN
// Resume:  http://pascal.kissian.net
//
// CopyRight (c) 2015-2019 Pascal KISSIAN
//
// Published under the MIT License
//          Consider it as a proof of concept!
//          No warranty of any kind.
//          Use and abuse at your own risks.
//========================================================================
// when we use the word ignore, that means that it is ignored during the obfuscation process (i.e. not obfuscated)

$conf->t_ignore_pre_defined_classes     = 'all';        // 'all' (default value) , 'none',  or array of pre-defined classes that you use in your software:
                                                        //      ex: array('Exception', 'PDO', 'PDOStatement', 'PDOException');
                                                        // As instantiation is done at runtime, it is impossible to statically determinate when a method call is detected, on which class the object belong.
                                                        // so, all method names that exists in a pre_defined_class to ignore are ignored within every classes.
                                                        // if you have some method names in your classes that have the same name that a predefine class method, it will not be obfuscated.
                                                        // you can limit the number of method names to ignore by providing an array of the pre-defined classes you really use in your software!
                                                        // same behaviour for properties...

$conf->t_ignore_constants               = null;         // array where values are names to ignore.
$conf->t_ignore_variables               = null;         // array where values are names to ignore.
$conf->t_ignore_functions               = null;         // array where values are names to ignore.
$conf->t_ignore_class_constants         = null;         // array where values are names to ignore.
$conf->t_ignore_methods                 = null;         // array where values are names to ignore.
$conf->t_ignore_properties              = null;         // array where values are names to ignore.
$conf->t_ignore_classes                 = null;         // array where values are names to ignore.
$conf->t_ignore_interfaces              = null;         // array where values are names to ignore.
$conf->t_ignore_traits                  = null;         // array where values are names to ignore.
$conf->t_ignore_namespaces              = null;         // array where values are names to ignore.
$conf->t_ignore_labels                  = null;         // array where values are names to ignore.

$conf->t_ignore_constants_prefix        = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_variables_prefix        = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_functions_prefix        = null;         // array where values are prefix of names to ignore.

$conf->t_ignore_class_constants_prefix  = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_properties_prefix       = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_methods_prefix          = null;         // array where values are prefix of names to ignore.

$conf->t_ignore_classes_prefix          = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_interfaces_prefix       = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_traits_prefix           = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_namespaces_prefix       = null;         // array where values are prefix of names to ignore.
$conf->t_ignore_labels_prefix           = null;         // array where values are prefix of names to ignore.

$conf->parser_mode                      = 'ONLY_PHP7';// allowed modes are 'PREFER_PHP7', 'PREFER_PHP5', 'ONLY_PHP7', 'ONLY_PHP5'
                                                        // see PHP-Parser documentation for meaning...

$conf->scramble_mode                    = 'identifier'; // allowed modes are 'identifier', 'hexa', 'numeric'
$conf->scramble_length                  = 5;            // min length of scrambled names (min = 2; max = 16 for identifier, 32 for hexa and numeric)

$conf->t_obfuscate_php_extension        = array('php'); // array where values are extensions of php files to be obfuscated.

$conf->obfuscate_constant_name          = true;         // self explanatory
$conf->obfuscate_variable_name          = true;         // self explanatory
$conf->obfuscate_function_name          = true;         // self explanatory
$conf->obfuscate_class_name             = true;         // self explanatory
$conf->obfuscate_interface_name         = true;         // self explanatory
$conf->obfuscate_trait_name             = true;         // self explanatory
$conf->obfuscate_class_constant_name    = true;         // self explanatory
$conf->obfuscate_property_name          = true;         // self explanatory
$conf->obfuscate_method_name            = true;         // self explanatory
$conf->obfuscate_namespace_name         = true;         // self explanatory
$conf->obfuscate_label_name             = true;         // label: , goto label;  obfuscation
$conf->obfuscate_if_statement           = true;         // obfuscation of  if else elseif statements
$conf->obfuscate_loop_statement         = true;         // obfuscation of  for while do while statements
$conf->obfuscate_string_literal         = true;         // pseudo-obfuscation of  string literals

$conf->shuffle_stmts                    = true;         // shuffle chunks of statements!  disable this obfuscation (or minimize the number of chunks) if performance is important for you!
$conf->shuffle_stmts_min_chunk_size     =    1;         // minimum number of statements in a chunk! the min value is 1, that gives you the maximum of obfuscation ... and the minimum of performance...
$conf->shuffle_stmts_chunk_mode         = 'fixed';      // 'fixed' or 'ratio' in fixed mode, the chunk_size is always equal to the min chunk size!
$conf->shuffle_stmts_chunk_ratio        =   20;         // ratio > 1  100/ratio is the percentage of chunks in a statements sequence  ratio = 2 means 50%  ratio = 100 mins 1% ...
                                                        // if you increase the number of chunks, you increase also the obfuscation level ... and you increase also the performance overhead!

$conf->strip_indentation                = true;         // all your obfuscated code will be generated on a single line
$conf->abort_on_error                   = true;         // self explanatory
$conf->confirm                          = true;         // rfu : will answer Y on confirmation request (reserved for future use ... or not...)
$conf->silent                           = false;        // display or not Information level messages.


$conf->source_directory                 = null;         // self explanatory
$conf->target_directory                 = null;         // self explanatory

$conf->t_keep                           = null;         // array of directory or file pathnames, to keep 'as is' (i.e. not obfuscate.)
$conf->t_skip                           = null;         // array of directory or file pathnames, to skip when exploring source tree structure ... they will not be on target!
$conf->allow_and_overwrite_empty_files  = true;         // allow empty files to be kept as is

$conf->max_nested_directory             =   99;
$conf->follow_symlinks                  = false;        // WARNING: setting it to true will copy the directory instead of replicating the link...
                                                        // WARNING: if there is a loop of links,  $conf->max_nested_directory can be created...

$conf->user_comment                     = null;         // user comment to insert inside each obfuscated file

$conf->extract_comment_from_line        = null;         // when both 2 are set, each obfuscated file will contain an extract of the corresponding source file,
$conf->extract_comment_to_line          = null;         // starting from extract_comment_from_line number, and ending at extract_comment_to_line line number.

?>

Suggestion: option to follow symlinks

Hi, sometimes it would be useful to follow symlinks instead of replicating them. Maybe only when the output directory is specified.
yakpro-po source_directory -o target_directory

Currently I commented out the if (is_link($source_path)) … block in

if (is_link($source_path))

to achieve this. :)

Thanks!

Issues with php 7.4

I know php7.4 is still not released but I wanted to share an issue I'm facing. (works well with other PHP versions)

Exception ParseError:syntax error, unexpected 'FN' (T_FN), expecting identifier (T_STRING)

In my particular case, I'm runnign it as:

yakpro-po/yakpro-po.php --scramble-length 2 --scramble-mode identifier --no-obfuscate-namespace-name --no-obfuscate-method-name --no-obfuscate-property-name --no-obfuscate-trait-name --no-obfuscate-interface-name --no-obfuscate-class-name --no-obfuscate-class_constant-name --no-obfuscate-constant-name --no-obfuscate-function-name

error on empty files

I have yakpropo sometimes processing php files containing only the php opener and a carriage return
"<?php
"

(that file has to be there and go through the obfuscator, Framework reasons, a standard file that is usually not empty but sometimes is).

As log says (below), it's probably an issue in PhpParser, but maybe yakpropo could have a workaround? It's not a blocking issue for me, I put a dummy code line in the file.

pStmts(Array, false) #1 C:\tortoise\Cortex\WebFramework\LTK\tools\yakpro-po\PHP-Parser\lib\PhpParser\PrettyPrinterAbstract.php(116): PhpParser\PrettyPrinterAbstract->prettyPrint(Array) #2 C:\tortoise\Cortex\WebFramework\LTK\tools\yakpro-po\include\functions.php(58): PhpParser\PrettyPrinterAbstract->prettyPrintFile(Array) #3 C:\tortoise\Cortex\WebFramework\LTK\tools\yakpro-po\yakpro-po.php(60): obfuscate('C:\tortoise\Cor...') #4 {main} thrown in C:\tortoise\Cortex\WebFramework\LTK\tools\yakpro-po\PHP-Parser\lib\PhpParser\PrettyPrinterAbstract.php on line 155 make[2]: **\* [C:/xampp/htdocs/Cux/Template/data.php] Error 255

Bloody html

Hello.
I have seen this:

Note: This tool has been written in order to obfuscate pure php sources. it is not intended to be used with html and embeded php inside (you may try to deactivate statements shuffling...). You can still embed html within php using the echo <<<END ... END; syntax!

How about converting embedded html to echo << END .. END syntax before obfuscation ? PHP-Parser can help with it ?

PHP file not usable anymore after obfuscation

Hello, thank you so much for your amazing tool.

I met a problem with your tool: I am trying to obfuscate some php webshell using your tool for research purpose. I tried to obfuscate this file using the default setting of your tool, and then the obfuscated file is not working. Do you have any idea why?

Thanks a lot.

Reserved class method names are scrambled under certain conditions

When limiting the scope of predefined functions which are scanned, the scrambler catches some reserved function names such as __call because they do not appear in any of the scanned predefined classes.

The reason for this is that in scrambler.php, line 265, t_ignore is populated with a list of reserved functions, not methods. No fancy example this time ;).

outer classes/methods should not be encoded

example:

  • new stdClass() : should not be encoded as it's not declared in the source folder (it's a standard class)
  • DomDocument::{whatever constant} : should not be encoded, as the DomDocument class is not declared in the source folder (standard class)

Until that is resolved, I have to deactivate obfuscation for classes and methods.
Well, I know it's minor glitches, overall good job !

obfuscation breaks array access in some cases

    public function getMapped(bool $named = false): array {
      $types = Duffs::getTypes();
      $clients = [];
      if(in_array("duff", $licenseTypes)){
          if($named){
              $clients["duff"] = $this->duff;
          } else {
              $clients[array_search("duff", $types)] = $this->duff;
          }
      }
      return $clients;
    }

this will end up of being assigned a null value for some reason, the array position will exist for my case as types is fine, but for some reason the assignment wont work

    public function getMapped(bool $KAqAA = false): array {
        goto uAVh4;
        mCkRt:
        $GhFDC["\x64\165\x66\146"] = $this->Y2GpO;
        goto OC0IH;
        xVc1l:
        if ($KAqAA) {
            goto W2Cf3;
        }
        goto SVjBD;
        BkqXo:
        return $GhFDC;
        goto JfBez;
        XvXVQ: W2Cf3:
        goto mCkRt;
        faMB6:
        $GhFDC = [];
        goto b5s0K;
        OC0IH: a5y0c:
        goto DJ1OH;
        SVjBD:
        $GhFDC[array_search("\144\x75\146\x66", $iYKZc)] = $this->Y2GpO;
        goto R6kua;
        DJ1OH: kmVls:
        goto BkqXo;
        uAVh4:
        $Ds0TU = Duffs::getTypes();
        goto faMB6;
        R6kua:
        goto a5y0c;
        goto XvXVQ;
        b5s0K:
        if (!in_array("\144\165\x66\146", $Ds0TU)) {
            goto kmVls;
        }
        goto xVc1l;
        JfBez:
    }

I think the issue is deeper, because the data is retrieved from an Object.
and the Method also gets obfuscated though the obfuscator has no concept of the objects contents.

    private function mapData(Object $data) : void{
      $this->duff = $data->duff;
    }

$data is JSON parsed via json_decode() so a native PHP object

but it becomes obfuscated too

    private function mapData(Object $mMRNs): void {
        $this->dM_Iz = $mMRNs->dM_Iz;
    }

Where dM_lz should stay duff because the object map stays the same even if obfuscated.

PHP Notice: A non well formed numeric value encountered in /usr/local/yakpro-po/include/check_version.php on line 25

At the end by running this command

yakpro-po --help

The error:

`PHP Notice: A non well formed numeric value encountered in /usr/local/yakpro-po/include/check_version.php on line 25
PHP Stack trace:
PHP 1. {main}() /usr/local/yakpro-po/yakpro-po.php:0
PHP 2. require_once() /usr/local/yakpro-po/yakpro-po.php:20

Notice: A non well formed numeric value encountered in /usr/local/yakpro-po/include/check_version.php on line 25

Call Stack:
0.0009 371808 1. {main}() /usr/local/yakpro-po/yakpro-po.php:0
0.0039 382688 2. require_once('/usr/local/yakpro-po/include/check_version.php') /usr/local/yakpro-po/yakpro-po.php:20

Error: Wrong version of PHP-Parser detected!
Currently, only 4.x branch of PHP-Parser is supported!
You can try to use the following command:
# git clone https://github.com/nikic/PHP-Parser.git
`

$t_ignore_methods is invalid, the specified method name cannot be ignored

$t_ignore_methods is invalid, can't ignore the specified method name, I am using version 2.0.4.
For example: I introduced the DB static class, I added all the public methods of the DB class to the array in $t_ignore_methods, set $obfuscate_method_name to true to perform obfuscation, and the result is that the DB class method is still confused.

!is_dir_writeable gets encrypted even if it's a primitive

Hi I got a fatal error trying to encrypt e file with this function in it
because yakpro renames !is_dir_writeable() to vcLmF()

My original code

<?php

class Tbuy_Imageflow_Model_From_Imageflow extends Tbuy_Flow_Model_From_Abstract
{
    const PROCESSED_IMAGES_DIR = 'processed';
    
	protected function getProcessedImagesDir() {
		$processed_images_dir = $this->getImagesPath().
            self::PROCESSED_IMAGES_DIR . DS .
            date('Y', time()) . DS .
            date('m', time()) . DS .
            date('d', time()) . DS;
        if (!is_dir($processed_images_dir)) {
            mkdir($processed_images_dir, 0777, true);
        }

        if (!is_dir_writeable($processed_images_dir)) {
            Mage::helper('imageflow')->log("Can not move processed photo to processed dir. Directory is not writable: {$processed_images_dir}");

            return null;
        }

        return $processed_images_dir;
    }

}

The converted code

<?php

class Tbuy_Imageflow_Model_From_Imageflow extends Tbuy_Flow_Model_From_Abstract
{
    const PROCESSED_IMAGES_DIR = "\x70\162\x6f\x63\x65\x73\x73\x65\144";
    protected function getProcessedImagesDir()
    {
        goto kGds_;
        kknU7:
        mkdir($SlSU7, 0777, true);
        goto gZmxS;
        hocLc:
        Gw1y_:
        goto nPOXa;
        f8qY3:
        return null;
        goto hocLc;
        kGds_:
        $SlSU7 = $this->getImagesPath() . self::PROCESSED_IMAGES_DIR . DS . date("\x59", time()) . DS . date("\155", time()) . DS . date("\144", time()) . DS;
        goto zREWq;
        gZmxS:
        lOHav:
        goto rvtAR;
        zREWq:
        if (is_dir($SlSU7)) {
            goto lOHav;
        }
        goto kknU7;
        rvtAR:
        if (vcLmF($SlSU7)) {
            goto Gw1y_;
        }
        goto D0fGD;
        D0fGD:
        Mage::helper("\x69\155\141\147\x65\x66\154\x6f\167")->log("\103\x61\156\x20\x6e\157\x74\x20\x6d\157\x76\x65\x20\160\x72\157\x63\x65\163\x73\x65\144\40\x70\150\x6f\x74\157\40\x74\157\x20\160\x72\157\143\145\163\163\145\x64\40\144\151\x72\56\40\x44\x69\x72\x65\x63\164\157\162\x79\x20\x69\x73\40\156\157\164\40\x77\162\151\164\x61\x62\x6c\x65\x3a\x20{$SlSU7}");
        goto f8qY3;
        nPOXa:
        return $SlSU7;
        goto p2_w3;
        p2_w3:
    }
}

This is the configuration used

yakpro-po.cnf

I've worked around it by setting

$conf->t_ignore_functions = ['is_dir_writeable']

Thank you very much
Andrea

manual install

I have php-parser installed via composer and I can't get yakpro to see it properly. I don't want to load the 9000 files required by git. If you can provide a basic outline of where things need to be it would be helpful

Issues scrambling php scripts

Hi, I'm testing your software on php scripts that can be launched on the command line. On these scripts there seem to be an issue because this code:

#!/usr/bin/php
<?php echo "123"; ?>

becomes this (comments stripped out)

<?php echo "\43\x21\57\x75\163\x72\x2f\142\x69\x6e\57\x70\x68\x70\12"; echo "\61\62\x33";
where \43\x21\57\x75\163\x72\x2f\142\x69\x6e\57\x70\x68\x70\12 is #!/usr/bin/php
instead of

#!/usr/bin/php
<?php echo "\61\62\x33"; ?>

Am I doing anything wrong?

Doesnt work with composer autoload

Getting this error:

Fatal error: Uncaught exception 'LogicException' with message 'Passed array does not specify an existing static method (class 'ComposerAutoloaderInit6abcfcd8de4a38fce2851d378ca1a6d0' not found)' in /var/www/domain/web/library/vendor/composer/autoload_real.php:8
Stack trace:
#0 /var/www/domain/web/library/vendor/composer/autoload_real.php(8): spl_autoload_register(Array, true, true)
#1 /var/www/domain/web/library/vendor/autoload.php(8): uUBET::gbBbi()
#2 /var/www/domain/web/base/init.php(8): include('/var/www/domain...')
#3 /var/www/domain/web/index.php(8): require('/var/www/domain...')
#4 {main}
thrown in /var/www/domain/web/library/vendor/composer/autoload_real.php on line 8

I believe it's relevant with this one: #13

Does not obfuscate string value

Trying with your demo, after decoding in unphp.net, I still can see "hello", "that's it!".... I used --obfuscate-string-literal, but It does not work :|


<?php
/*--------------------------
    simple test program !
---------------------------*/
$hello      = "hello ";
$world      = "world ";
$what       = "what ";
$a          = "a ";
$beautiful  = "beautiful ";
$day        = "day ";

for($i=0;$i<=7;++$i)        // small loop!
{
    echo $hello;    echo $world;                                echo PHP_EOL;
    echo $what;     echo $a;    echo $beautiful;    echo $day;  echo PHP_EOL;
}
echo "that's it!".PHP_EOL;
?>

Change shebang and permissions of yakpro-po.php

Hello,

the main file's shebang points to /usr/bin/php. This is not the convention and will cause trouble on systems with multiple PHP installations, especially because the output of the script depends on the PHP environment and its installed addons.

Please change the first line to #!/usr/bin/env php so that the shell's active PHP version is used.

Your README file also specifies that the main PHP file should be made executable. Right now, every pull on my *nix platforms results in a conflict due to incorrect permissions, so that I have to revert permissions before pulling/merging. Why not include the correct permissions with the git repository right away? On *nix, just chmod +x and git add the file again. On Windows, the git update-index --chmod=+x yakpro-po.php command would have the same effect because there is no executable bit on Windows.

Cheers, Oliver

Scrambled labels might match reserved words

Hi, thanks for the nice project! :)

I set $conf->scramble_length = 2; to make things smaller (and I'm just experimenting anyways), but PHP complained:
PHP Parse error: syntax error, unexpected 'aS' (T_AS), expecting identifier (T_STRING)

This was the show-stopping expression:
goto aS;

While $-prefixed variable names are not affected, labels, class names, constants, etc. won't really like if they are renamed for reserved words.

Maybe a reserved word list should be included ( http://php.net/reserved )?

problem with dynamic properties

a code sample:

$data = '{"prop":"val"}';
$data = json_decode($data);

if (isset($data->prop)) {
    echo 'true';
} else {
    echo 'false';
}

returns true and will be encoded as:

goto DHKg9; yqEUg: echo "\x74\x72\x75\x65"; goto R9s06; U99Jy: $QwkQT = json_decode($QwkQT); goto J4ocS; qtu0F: echo "\146\141\154\163\145"; goto cN9Mc; DHKg9: $QwkQT = "\x7b\x22\x70\162\x6f\x70\x22\x3a\x22\166\141\x6c\42\x7d"; goto U99Jy; J4ocS: if (isset($QwkQT->i348Y)) { goto YGJH6; } goto qtu0F; CPTcV: YGJH6: goto yqEUg; cN9Mc: goto MsDzS; goto CPTcV; R9s06: MsDzS:

return false

Run the obfuscated project

How can I run the obfuscated project in wamp server ? is there any loader like other obfuscation tools zend, ioncube , source guardien ?

Comment

Is it possible to run yakpro without removing comments?

thank you.

problem with global vars !

I have problem with code after obfuscation if It has a variables in global array :
this original :
`<?php
ini_set("display_errors",true);
class cc {
function ee (){
echo ("test");
}
}
$GLOBALS["xc"] = new cc();

function vv (){
global $xc;
$xc->ee();
}
vv();

?>`

this after modify :
<?php /* __________________________________________________ | Obfuscated by YAK Pro - Php Obfuscator 2.0.4 | | on 2020-01-09 14:47:59 | | GitHub: https://github.com/pk-fr/yakpro-po | |__________________________________________________| */ goto TWmXm; I1BoU: $GLOBALS["xc"] = new cc(); goto aNeS0; TWmXm: ini_set("display_errors", true); goto IHi_O; IHi_O: class cc { function ee() { echo "test"; } } goto I1BoU; aNeS0: function qtRlm() { global $SyCuk; $SyCuk->ee(); } goto HOmQB; HOmQB: QTrLM();

when run , it's show error :

PHP Fatal error: Uncaught Error: Call to a member function ee() on null

Is there any config for solve this problem ?

String used calls

Example:
class test { function out (){ echo 'test text'; } } $t = new test; call_user_func_array ([$t, 'out'], []);

The problem is the string "out" :-(
Please fix this bug.

how to unobfuscate the result

Today I got a file obfuscated by your tool. I can not read the file clearly. So how to unobfuscate the file so that I can read it easily?

Lambda captured variables are not scrambled

Test case:

<?php
$mapTable = [1=>2, 2=>3, 3=>4];
$input    = [1, 2, 3];
$result   = array_map(function ($elem) use ($mapTable) {
    return $mapTable[$elem];
}, $input);
// $result is now [2, 3, 4]

Example output:

$ yakpro-po testUseScrambling.php --no-strip-indentation --no-shuffle-statements 
<?php

$pc7UO = array(1 => 2, 2 => 3, 3 => 4);
$Vb40o = array(1, 2, 3);
$MO9uG = array_map(function ($lCrNn) use($mapTable) {
    return $pc7UO[$lCrNn];
}, $Vb40o);

The obfuscator should have emitted $pc7UO instead of $mapTable for the code to be equivalent to the input.

Missing instanceof support

Class names in expression "instanceof " are not obfuscated.

Patch suggestion:
/includes/classes/parser_extensions/my_node_visitor.php

+214:
|| ($node instanceof PhpParser\Node\Expr\Instanceof_)

+569
if ($node instanceof PhpParser\Node\Expr\Instanceof_)
            {
                if (isset($node->{'class'}->parts))
                {
                    $parts = $node->{'class'}->parts;
                    for($i=0;$i<count($parts)-1;++$i)
                    {
                        $name  = $parts[$i];
                        if ( is_string($name) && (strlen($name) !== 0) )
                        {
                            $r = $scrambler->scramble($name);
                            if ($r!==$name)
                            {
                                $node->{'class'}->parts[$i] = $r;
                                $node_modified = true;
                            }
                        }
                    }
                }
            }

Cannot obfuscate simple WordPress plugin

I cannot obfuscate a simple WordPress plugin (like https://wordpress.org/plugins/disable-google-fonts/) with your tool but it works with other tools (like https://github.com/naneau/php-obfuscator).

In /var/www/html/wordpress/wp-content/plugins, I execute ~/Downloads/yakpro-po/yakpro-po.php disable-google-fonts -o disable-google-fonts-dev

I don't know if we need to keep the files generated in the folder yakpro-po, so I tried to keep them (I got a fatal error message when I tried without keeping the folder).

To keep the yakpro-po folder structure, I created a main file disable-google-fonts.php in the folder disable-google-fonts-dev with these basic informations to load the WordPress plugin:

<?php
/**
 * Plugin Name: Disable Google Fonts Dev
 */

require_once 'yakpro-po/obfuscated/disable-google-fonts.php';

When I try to activate the plugin in the WordPress admin area, I still get the error message (there is no function named WeIzo in the original plugin, it looks like an obfuscated name):

Fatal error: Uncaught Error: Call to undefined function WeIzo() in /var/www/html/wordpress/wp-content/plugins/disable-google-fonts-dev/yakpro-po/obfuscated/disable-google-fonts.php:8 Stack trace: #0 /var/www/html/wordpress/wp-content/plugins/disable-google-fonts-dev/yakpro-po/obfuscated/disable-google-fonts.php(8): DcYMB->__construct() #1 /var/www/html/wordpress/wp-content/plugins/disable-google-fonts-dev/disable-google-fonts.php(6): require_once('/var/www/html/w...') #2 /var/www/html/wordpress/wp-admin/includes/plugin.php(1897): include('/var/www/html/w...') #3 /var/www/html/wordpress/wp-admin/plugins.php(172): plugin_sandbox_scrape('disable-google-...') #4 {main} thrown in /var/www/html/wordpress/wp-content/plugins/disable-google-fonts-dev/yakpro-po/obfuscated/disable-google-fonts.php on line 8

Edit: my copy-paste of the error message referenced several unrelated issues because of the '#' character, I don't know if we can avoid this.

Suggestion: open API for extensions

First of all great work. Great tool.

My only suggestion is to allow us to have an API to write our own code selection strategy - with options to affect the selected obfuscated files and also do search / replace for references on ignored files.

So for example: if I wanted to write a obfuscation selector to replace methods inside add_action() functions on a WP plugin, and do a global search / replace on all instances (where this method is called) on non-obfuscated files with the new obfuscated method name (so it does not break the codebase) - this would be very useful to have on an extension for yakpro-po

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.