news 2026/4/23 16:52:38

PicoCTF writeup - picoMini —— Pico Bank

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PicoCTF writeup - picoMini —— Pico Bank

Today, We will begin the hardest part of the picoMini writeup——Pico Bank.

Now look at the question


and the hints.



I choose android-killer to inspect the apk.(you can also use other app like apktool or jadxGUI)


Open the pico-bank app in Mumu simulator.

before we login, we must know the password.

Try to find it in the source code!


search "login"


we can see the login.smali.

Click it.


We can find the username and password in the login$1.smali


Login now.

username:johnson password:tricky1990

And we can see this.

Then we need to find the OTP value.


Try to search the OTP.


Find it! So easy.

The otp is 9673


Here is the page after we login.


Look at the notification.

It seems that we need to check the server's responce , so we have to enter the otp again😭.


And we need to investigate the history data.

It looks like binary code, because it is composed of 0 and 1.


Try to write down all the numbers.

1110000 1101001 1100011 1101111 1000011 1010100 1000110 1111011 110001 1011111 1101100 110001 110011 1100100 1011111 110100 1100010 110000 1110101 1110100 1011111 1100010 110011 110001 1101110 1100111 1011111

Throw it to Deepseek,let AI to transfer the binary code into ASCII.


so the first part of the flag is

picoCTF{1_l13d_4b0ut_b31ng_

OK. Now ,we need to find another part of it.

FIRST,try to get some hint in the source code.

We need to find out how the server handle the responce.

# annotations .annotation system Ldalvik/annotation/EnclosingMethod; value = Lcom/example/picobank/OTP;->verifyOtp(Ljava/lang/String;)V .end annotation .annotation system Ldalvik/annotation/InnerClass; accessFlags = 0x0 name = null .end annotation .annotation system Ldalvik/annotation/Signature; value = { "Ljava/lang/Object;", "Lcom/android/volley/Response$Listener<", "Lorg/json/JSONObject;", ">;" } .end annotation # instance fields .field final synthetic this$0:Lcom/example/picobank/OTP; # direct methods .method constructor <init>(Lcom/example/picobank/OTP;)V .locals 0 .param p1, "this$0" # Lcom/example/picobank/OTP; .line 86 iput-object p1, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method .method public onResponse(Lorg/json/JSONObject;)V .locals 8 .param p1, "response" # Lorg/json/JSONObject; .line 90 const-string v0, "hint" const-string v1, "flag" :try_start_0 const-string v2, "success" invoke-virtual {p1, v2}, Lorg/json/JSONObject;->getBoolean(Ljava/lang/String;)Z move-result v2 .line 91 .local v2, "success":Z if-eqz v2, :cond_0 .line 92 invoke-virtual {p1, v1}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String; move-result-object v3 .line 93 .local v3, "flag":Ljava/lang/String; invoke-virtual {p1, v0}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String; move-result-object v4 .line 95 .local v4, "hint":Ljava/lang/String; new-instance v5, Landroid/content/Intent; iget-object v6, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; const-class v7, Lcom/example/picobank/MainActivity; invoke-direct {v5, v6, v7}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V .line 96 .local v5, "intent":Landroid/content/Intent; invoke-virtual {v5, v1, v3}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent; .line 97 invoke-virtual {v5, v0, v4}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent; .line 98 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-virtual {v0, v5}, Lcom/example/picobank/OTP;->startActivity(Landroid/content/Intent;)V .line 99 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-virtual {v0}, Lcom/example/picobank/OTP;->finish()V .line 100 .end local v3 # "flag":Ljava/lang/String; .end local v4 # "hint":Ljava/lang/String; .end local v5 # "intent":Landroid/content/Intent; goto :goto_0 .line 101 :cond_0 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; const-string v1, "Invalid OTP"

We know that, the otp_value was firstly passed to VERIFYOTP , then, if the value is correct ,we can see the flag.

Try search the verifyotp

.method private verifyOtp(Ljava/lang/String;)V .locals 10 .param p1, "otp" # Ljava/lang/String; .line 67 const-string v0, "your server url" .line 68 .local v0, "severUrl":Ljava/lang/String; new-instance v1, Ljava/lang/StringBuilder; invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 const-string v2, "/verify-otp" invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v1 .line 70 .local v1, "endpoint":Ljava/lang/String; invoke-virtual {p0}, Lcom/example/picobank/OTP;->getResources()Landroid/content/res/Resources; move-result-object v2 sget v3, Lcom/example/picobank/R$string;->otp_value:I invoke-virtual {v2, v3}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String; move-result-object v2 invoke-virtual {v2, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z move-result v2 if-eqz v2, :cond_0 .line 71 new-instance v2, Landroid/content/Intent; const-class v3, Lcom/example/picobank/MainActivity; invoke-direct {v2, p0, v3}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V .line 72 .local v2, "intent":Landroid/content/Intent; invoke-virtual {p0, v2}, Lcom/example/picobank/OTP;->startActivity(Landroid/content/Intent;)V .line 73 invoke-virtual {p0}, Lcom/example/picobank/OTP;->finish()V .line 74 .end local v2 # "intent":Landroid/content/Intent; goto :goto_0 .line 75 :cond_0 const-string v2, "Invalid OTP"

Here in the code , our server url is connected with the "/verify-otp".

like this.


And then we need to POST the otpvalue to server .

Use burpsuite.


Don't forget to add the Content-type , otherwise it will fail.


Here is the response.


So the second part of the flag is

s3cur3d_m0b1l3_l0g1n_e9d3786f}

OK! Still so easy today!🥳See you!

flag

picoCTF{1_l13d_4b0ut_b31ng_s3cur3d_m0b1l3_l0g1n_e9d3786f}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 14:21:06

KaLM-Embedding-V2.5:0.5B参数的轻量级嵌入革命

KaLM-Embedding-V2.5&#xff1a;0.5B参数的轻量级嵌入革命 ——基于PyTorch-CUDA基础镜像的高效部署实践 在AI模型越做越大的今天&#xff0c;有没有可能反其道而行之&#xff1f;不是堆叠千亿参数&#xff0c;而是用不到1%的体量&#xff0c;实现接近专业级语义理解的能力&am…

作者头像 李华
网站建设 2026/4/18 10:07:27

Dify开源LLM应用开发平台部署与使用指南

Dify 开源 LLM 应用开发平台部署与使用指南 在生成式 AI 技术快速落地的今天&#xff0c;越来越多团队希望将大模型能力嵌入业务流程——无论是智能客服、知识问答&#xff0c;还是自动化内容生成。但直接调用 API 写代码&#xff0c;往往面临维护成本高、Prompt 难管理、迭代…

作者头像 李华
网站建设 2026/4/19 10:11:04

景杰生物第五届生信研修班圆满落幕!引领技术协同创新,推动精准医学产业化进程

2025年9月19日&#xff0c;由杭州景杰生物科技股份有限公司主办的“智启未来&#xff1a;AI赋能蛋白组学与生信高级研修班”在杭州顺利闭幕。本次研修班以“蛋白质组学前沿热点分享”“AI在蛋白质组学及生信中的前沿应用”为核心内容&#xff0c;来自北京大学、复旦大学、浙江大…

作者头像 李华
网站建设 2026/4/18 9:44:45

打造个性化AI门户:LobeChat主题与UI定制技巧分享

打造个性化AI门户&#xff1a;LobeChat主题与UI定制技巧分享 在企业纷纷拥抱大模型的今天&#xff0c;一个常被忽视的问题浮出水面&#xff1a;为什么我们有了强大的AI能力&#xff0c;用户却依然觉得“不好用”&#xff1f; 答案往往藏在前端——再聪明的模型&#xff0c;如…

作者头像 李华